引言:
ThingsBoard是乌克兰一个团队开发的物联网系统,其功能和性能在业内口碑极佳,国内较多公司基于ThingsBoad搭建自己的物联网系统。为了能使大家更好的了解和使用该系统而写作本文,希望能对大家有所帮助!
ThingsBoard的部署模式包括单节点部署和微服务方式部署,微服务方式部署大概又分为3种方式:
- 主机或容器方式部署;
- Docker Compose方式部署;
- K8S方式部署;
物联网平台其运行环境一般属于稳态环境,流量比较规律,运行于其上的业务系统也比较成熟,因此K8S系统的缩扩容、熔断、限流等和运维相关的大部分功能使用频率极低。如果采用K8S系统作为物联网PAAS层的基础,对运维的要求较高,且应用系统要做相关的迁移改造,ROI太低。除非引入基于K8S的PAAS平台是企业架构演进的一步工作,否则单个物联网系统或基于物联网的业务应用(比如智慧楼宇应用),并不建议采用K8S方式部署。而主机或容器方式部署,相比较于Docker Compose方式部署自动化程度较低,因此建议采用Docker Compose方式部署。
本文通过在4个节点上部署ThingsBoard物联网系统,作为讲解采用Docker Compose方式部署ThingsBoard的例子,该例子中ThingsBoard物联网系统的版本为PE 3.2.2。本文先介绍4节点例子的部署架构,通过讲解ThingBoard基于微服务的技术架构,使读者了解ThingsBoard所包含的微服务。基于上述的理解,再讲解4节点部署架构下,各微服务在各节点的分布情况。第二章详细讲解ThingsBoard系统的配置。第三章从初始化、常用指令、启动顺序等方面,详细讲解ThingsBoard如何运维。
4结点布署设计

ThingsBoard微服务架构图(图片来自ThingsBoard官网)
上图为ThingsBoard物联网系统微服务架构图,其中深蓝色部分为ThingsBoard物联网系统的核心微服务,分别为Transport、UI、Rule Engine、Core以及在图上没有展示的Js Excecutor微服务。除了核心的几个微服务外,还包括为核心微服务提供基础服务的几个技术组件类微服务,它们分别是:
- 用于数据存储的PostgreSQL数据库(SQL database类)微服务、Cassandra数据库(NoSQL DataBase 类)微服务,以及在图上没有展示的Redis(缓存数据库类)微服务;
- 用于实现消息发布订阅的消息队列Kafka微服务;
- 用于共享配置以及其它功能的Zookeeper微服务(上图未展示);
- 用于提供负载均衡功能的微服务(上图未展示);

4节点部署架构图
本文通过一个4节点的部署案例,来举例解释ThingsBoard的部署。各节点运行的微服务分配情况,如上图所列。其中,ThingsBoard官网提供的例子中,使用HAProxy实现负载均衡功能,由于本人相比较而言更了解Nginx,因此用Nginx替代HAProxy。
系统配置详解
Docker Compose配置关键点说明
在这里先介绍ThingsBoard系统的Docker Compose配置文件中的一些关键配置点,通过了解这些关键配置点,便于更好的了解如何利用Docker Compose和Docker容器的功能,为应用系统提供运行环境相关的基础支持。
一、本机目录挂载
在docker-compose.yml文件中,通过配置目录映射达到实现下述功能:
1.将文件保存在服务器本地,容器重启后数据不丢失,比如将服务器目录映射到PostgeSQL数据库容器,用于保存数据库文件到服务器目录;
volumes:
- ./tb-node/postgres/data:/var/lib/postgresql/data
2.将配置文件通过目录映射,加载到容器中,实现修改运行在容器内系统的配置,比如:
volumes:
- ./tb-node/conf:/config
3.将修改后代码通过Jar包映射到容器内,实现修改后的应用代码发布功能,比如:
volumes:
- ./tb-node/tb-core:/usr/share/thingsboard/bin
二、时区设置
容器在运行时默认时区不一定是我们期望的时区,如果时区不正确,将可能造成数据记录、打印的日志等和时间相关的信息不正确。在docker-compose.yml文件中,通过配置可以实现让容器在指定时区运行,比如:
environment:
TZ: Asia/Shanghai
三、端口和主机网络
容器运行期间需要将端口映射到本地服务器或直接和本地服务器用同一个网络,可通过在docker-compose.yml文件中做下列三种配置方式实现:
1.将容器某端口映射到主机服务器指定端口,比如:
ports:
- "8088:8080"
2.将容器端口映射到主机服务器任意端口,比如:
ports:
- "8080"
3.容器和主机共用网络,比如:
network_mode: "host"
四、容器内添加hosts域名解析
在没有DNS情况下,需要通过添加hosts主机域名解析替代DNS功能,实现通过域名加端口号访问服务,而不是通过IP地址加端口访问服务。在docker-compose.yml文件中,通过下列配置实现向容器内添加hosts域名解析:
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
五、环境变量配置
在容器运行过程中,往往需要调整容器内的环境变量,我们可以通过在docker-compose.yml文件中加入env_file配置,实现调整容器内环境变量的值:
env_file:
- tb-node.env
- queue-kafka.env
各微服务配置说明
一、postgresql
Thingsboard微服务架构下,数据库采用混合模式,其中关系型数据库使用PostgresSQL。本例中,PostgreSQL微服务的配置如下所列:
postgres:
restart: always
image: "postgres:12"
network_mode: "host"
deploy:
resources:
limits:
cpus: '2'
memory: 8G
reservations:
cpus: '0.5'
memory: 200M
environment:
POSTGRES_DB: thingsboard
POSTGRES_USER: postgres
POSTGRES_PASSWORD: 密码
PG_DATA: /var/lib/postgresql/data
TZ: Asia/Shanghai
volumes:
- ./tb-node/postgres/data:/var/lib/postgresql/data
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
本例中数据库配置为单节点,为了确保数据库安全可靠,需要做冷热备份。热备建议采用数据库从库同步数据,请参考网上相关资料配置。
数据库访问权限和数据库通用配置,在docker\tb-node\postgres目录下的pg_hba.conf和postgresql.conf配置文件中,具体配置请参考附件。
二、cassandra
Cassandra集群采用3节点集群,分别部署在iot.node6、iot.node7、iot.node8三个节点上。iot.node6节点的配置如下所列:
cassandra:
restart: always
image: "cassandra:3.11.3"
network_mode: "host"
environment:
- CASSANDRA_BROADCAST_ADDRESS=iot.node6
- TZ=Asia/Shanghai
volumes:
- ./cassandra/data:/var/lib/cassandra
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
iot.node7和iot.node8两个节点的配置和iot.node6节点的配置基本相同,差异部分分别如下所列:
environment:
- CASSANDRA_BROADCAST_ADDRESS=iot.node7
- CASSANDRA_SEEDS=iot.node6
和
environment:
- CASSANDRA_BROADCAST_ADDRESS=iot.node8
- CASSANDRA_SEEDS=iot.node6
三、redis
本例中redis为单节点配置,其中通过command指令实现关闭redis持久化,具体配置如下所示:
redis:
restart: always
image: redis:4.0
ports:
- "6379:6379"
environment:
TZ: Asia/Shanghai
volumes:
- ./tb-node/redis.conf:/etc/redis/redis.conf
- ./tb-node/redis/data:/data
#900秒之内有1次更新,就进行持久化操作
#300秒之内有100次更新,就进行持久化操作
#60秒之内有1000次更新,就进行持久化操作
#command: redis-server --appendonly yes --save 900 1 --save 300 100 --save 60 1000 --dir .
command: redis-server --appendonly false --save ""
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
四、zookeeper
Zookeeper集群采用三节点部署,分别部署在iot.node6、iot.node7、iot.node8三个节点上。iot.node6节点的配置如下所列:
zookeeper:
restart: always
image: "zookeeper:3.5"
network_mode: "host"
environment:
ZOO_MY_ID: 1
ZOO_SERVERS: server.1=iot.node6:2888:3888;2181 server.2=iot.node7:2888:3888;2181 server.3=iot.node8:2888:3888;2181
TZ: Asia/Shanghai
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
iot.node7和iot.node8两个节点的配置和iot.node6节点的配置基本相同,差异部分分别如下所列:
environment:
ZOO_MY_ID: 2
和
environment:
ZOO_MY_ID: 3
五、kafka
Kafka采用三节点部署,分别部署在iot.node6、iot.node7、iot.node8三个节点上。iot.node6节点的配置如下所列:
kafka:
restart: always
image: "wurstmeister/kafka:2.13-2.6.0"
network_mode: "host"
ports:
- "9092:9092"
env_file:
- kafka.env
depends_on:
- zookeeper
environment:
KAFKA_BROKER_ID:1
TZ: Asia/Shanghai
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
iot.node7和iot.node8两个节点的配置和iot.node6节点的配置基本相同,差异部分分别如下所列:
environment:
KAFKA_BROKER_ID:2
和
environment:
KAFKA_BROKER_ID:3
kafka集群中和kafka相关的配置在kafka.env文件中。
六、tb-transport
ThingsBoard支持3类transport,分别为http、mqtt和coap。为了实现高可用分别在iot.node8、iot.node9两个节点各部署一套微服务。其配置如下所列:
tb-mqtt-transport:
restart: always
image: docker.io/thingsboard/tb-mqtt-transport:3.2.2
ports:
- "2883:1883"
environment:
TB_SERVICE_ID: tb-mqtt-transport1
TZ: Asia/Shanghai
env_file:
- tb-mqtt-transport.env
- queue-kafka.env
volumes:
- ./tb-transports/mqtt/conf:/config
- ./tb-transports/mqtt/log:/var/log/tb-mqtt-transport
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
tb-http-transport:
restart: always
image: docker.io/thingsboard/tb-http-transport:3.2.2
ports:
- "8081:8081"
environment:
TB_SERVICE_ID: tb-http-transport1
TZ: Asia/Shanghai
env_file:
- tb-http-transport.env
- queue-kafka.env
volumes:
- ./tb-transports/http/conf:/config
- ./tb-transports/http/log:/var/log/tb-http-transport
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
tb-coap-transport:
restart: always
image: docker.io/thingsboard/tb-coap-transport:3.2.2
ports:
- "5683:5683/udp"
environment:
TB_SERVICE_ID: tb-coap-transport
TZ: Asia/Shanghai
env_file:
- tb-coap-transport.env
- queue-kafka.env
volumes:
- ./tb-transports/coap/conf:/config
- ./tb-transports/coap/log:/var/log/tb-coap-transport
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
它们通过tb-XXX-transport.env、queue-kafka.env两个文件分别配置和zookeeper、kafka的连接参数以及自身服务所监听的端口。
七、tb-js-executor
规则链的js脚本在tb-js-executor服务中执行,为了提高执行效率,分别在iot.node6、iot.node7、iot.node9 三个节点上部署一套该服务,而且每个节点的该微服务副本数为20。其配置如下所列:
tb-js-executor:
restart: always
image: docker.io/thingsboard/tb-js-executor:3.2.2
# scale: 10
deploy:
mode: replicated
replicas: 20
env_file:
- tb-js-executor.env
- queue-kafka.env
environment:
TZ: Asia/Shanghai
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
它通过tb-js-executor.env、queue-kafka.env两个文件分别配置和kafka的连接参数以及自身服务相关的配置。
八、tb-rule-engine、tb-core
tb-core和tb-rule-engine两个服务用于接收来自API的时序数据、来自transport的遥测数据、属性变更和系统事件等信息,并由此调用相关规则链。为了实现高可用以及提高服务执行效率,分别在iot.node6、iot.node7、iot.node9三个节点上部署一套该服务。tb-core和tb-rule-engine服务配置基本相同,两者使用同一个镜像,彼此通过环境变量TB_SERVICE_TYPE来互相区别:
image: docker.io/thingsboard/tb-node:3.2.2
它们通过tb-node.env和queue-kafka.env两个文件来配置服务和zookeeper、redis、postgreSQL、kafka、cassandra的连接,连接配置参考附件以及源代码thingsboard-master\application\src\main\resources目录下的thingsboard.yml文件:
env_file:
- tb-node.env
- queue-kafka.env
tb-core的配置举例如下:
tb-core:
restart: always
image: docker.io/thingsboard/tb-node:3.2.2
ports:
- "6080:8080"
logging:
driver: "json-file"
options:
max-size: "200m"
max-file: "30"
environment:
TB_SERVICE_ID: tb-core
TB_SERVICE_TYPE: tb-core
TZ: Asia/Shanghai
env_file:
- tb-node.env
- queue-kafka.env
volumes:
- ./tb-node/conf:/config
- ./tb-node/log:/var/log/thingsboard
depends_on:
# - redis
- tb-js-executor
- tb-rule-engine
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
tb-rule-engine的配置举例如下:
tb-rule-engine:
restart: always
image: docker.io/thingsboard/tb-node:3.2.2
ports:
- "3080:8080"
logging:
driver: "json-file"
options:
max-size: "200m"
max-file: "30"
environment:
TB_SERVICE_ID: tb-rule-engine1
TB_SERVICE_TYPE: tb-rule-engine
TZ: Asia/Shanghai
env_file:
- tb-node.env
- queue-kafka.env
volumes:
- ./tb-node/conf:/config
- ./tb-node/log:/var/log/thingsboard
- ./tb-node/tb-rule-engine:/usr/share/thingsboard/bin
depends_on:
# - redis
- tb-js-executor
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
九、tb-web-ui
该微服务为ThingsBoard系统的管理后台,为了实现服务高可用,分别在iot.node6、iot.node7、iot.node9三台服务器各部署一套该服务。其配置如下:
tb-web-ui:
restart: always
image: docker.io/thingsboard/tb-web-ui:3.2.2
ports:
- "8088:8080"
env_file:
- tb-web-ui.env
volumes:
- ./tb-node/tb-web-ui:/usr/share/tb-web-ui
environment:
TZ: Asia/Shanghai
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
十、tb-nginx、tb-lb-mqtt
微服务tb-lb-mqtt用于提供tb-mqtt-transport的负载均衡功能,tb-nginx用于提供除tb-mqtt-transport外的所有对外服务和API的负载均衡功能,两者的配置如下所示:
tb-nginx:
restart: always
image: nginx:stable
ports:
- "8800:8800"
volumes:
- ./nginx/ui.conf:/etc/nginx/conf.d/ui.conf
- ./log/nginx:/var/log/nginx
environment:
TZ: Asia/Shanghai
links:
- tb-core
- tb-web-ui
- tb-http-transport
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
tb-lb-mqtt:
restart: always
image: docker.io/tekn0ir/nginx-stream:latest
ports:
- "8083:80"
volumes:
- ./nginx/stream_conf.d:/opt/nginx/stream.conf.d
- ./log/nginx/mqtt:/var/log/nginx
environment:
TZ: Asia/Shanghai
links:
- tb-mqtt-transport
extra_hosts:
- "iot.node6:192.168.64.6"
- "iot.node7:192.168.64.7"
- "iot.node8:192.168.64.8"
- "iot.node9:192.168.64.9"
负载均衡的具体配置参考./nginx/ui.conf和./nginx/stream_conf.d/mqtt.conf两个文件
日常运维
一、常用指令
Docker Compose常用指令包括:
1.启动某个服务指令up,比如启动zookeeper服务:
docker compose up zookeeper -d
2.停止服务指令stop,比如停止zookeeper服务:
docker compose stop zookeeper
3.删除服务指令rm,比如删除zookeeper 服务:
docker compose rm zookeeper
4.启动服务器上所有服务
docker compose up -d
5.停止并删除服务器上所有服务
docker compose down
6.查看某个服务的日志:
docker compose logs zookeeper | more
docker compose logs zookeeper -f
二、安装与初始化
1.安装规划
参考上一章节4节点部署设计内容
2.镜像安装
如果节点不能够访问外网,需要在能够访问外网的服务器上下载相关镜像,并将镜像装载到本地镜像库;
3.配置系统
为各节点配置相关文件,并将配置文件上传到Docker Compose运行目录,比如/datas/iottb/runtime/docker,具体目录结构和配置文件内容,参考附件;
4.启动各节点上的微服务
由于有的微服务依赖其它微服务,而docker compose的服务依赖配置只能设置启动的先后,并不能等一个服务完全启动后再启动对应服务。因此需要手动按顺序启动各微服务。各服务的启动顺序如下所列:
zookeeper -> (kafka|transport)
(zookeeper|redis|tb-js-executor) -> rule-engine->tb-core
其中,kafka和transport服务依赖zookeeper服务,tb-core服务依赖rule-engine服务,rule-engine服务依赖zookeeper、redis和tb-js-executor服务。需确定所依赖的服务启动成功后,再启动相应服务。
5.初始化PostgreSQL和Cassandra数据库
下载ThingsBoard源代码,PostgreSQL数据库初始化SQL语句在源代码的下列文件中:
thingsboard-master\dao\src\main\resources\*.sql
thingsboard-master\dao\src\test\resources\sql\system-data.sql
通过下列命令初始化PostpreSQL:
docker exec -it docker-postgres-1 bash #进入PostgreSQL 容器
psql -h 127.0.0.1 -dthingsboard -Upostgres -W #进入数据库
ALTER USER postgres WITH PASSWORD '新密码'; #修改postgres用户密码
CREATE DATABASE thingsboard; #创建thingsboard数据库
\d thingsboard; #切换到thingsboard数据
执行sql
通过修改docker\tb-node\postgres目录下的pg_hba.conf和postgresql.conf配置文件,配置数据库访问权限和优化数据库配置,并重启PostgresSQL服务使配置生效。
Cassandra的初始化语句在源代码的下列文件中:
thingsboard-master\dao\src\main\resources\*.cql
通过下列命令初始化Cassandra:
docker cp XXX.cql Cassandra容器ID:/root/XXX.cql #拷贝CQL文件到Cassandra容器
docker exec -it docker_cassandra_1 bash #进入Cassandra容器
cqlsh #进入Cassandra数据库
update system.local set cluster_name = 'Thingsboard Cluster' where key='Test Cluster'; #修改Cassandra集群名称
exit; #退出Cassandra数据库
nodetool flush system #使修改生效
cqlsh -f /root/XXX.cql #执行初始化脚本
nodetool flush system #使修改生效
6.初始化WidGet部件库
用系统管理员账户登录管理界面,在“部件库->部件包->+按钮->导入部件组”页面中,将thingsboard-master\application\src\main\data\json\system\widget_bundles目录下的插件拖到管理界面中,实现添加WidGet部件。
三、缩扩容
敬请期待后续文章。
四、查看日志
我们能够通过两种方式查看日志,一种方式为通过前面“常用指令”章节中提到的docker compose logs命令查看日志;另一种方式为登录节点服务器,进入容器内日志映射到服务器本地的目录,在目录下查看相关日志。
五、数据库备份
从安全的角度考虑,数据库需要做冷热备份,热备份通过数据库的主从同步实现,冷备份通过全量导出实现,具体实现参考下列脚本:
docker exec -it docker-postgres-1 #进入PostgreSQL数据库容器
export PGPASSWORD=数据库密码 #将数据库密码赋给环境变量
pg_dump -hlocalhost -U postgres -d thingsboard -w -Fc -Z 9 -f ./tb_20220705 & #后台运行导出命令
exit #退出PostgreSQL数据库容器
docker cp docker-postgres-1:/tb_20220705.sql /datas/iottb/runtime #从容器中拷贝备份文件到服务器本地
scp /datas/iottb/runtime/tb_20220705 root@iot.node6:/datas/iottb/runtime #将备份文件拷贝到其它服务器备份
六、监控
敬请期待后续文章。


本文详细介绍了如何使用Docker Compose在4个节点上部署ThingsBoard物联网系统,重点讨论了部署架构、关键配置以及日常运维操作。推荐采用Docker Compose方式,而非K8S,以简化部署流程。内容涵盖微服务分布、配置详解、初始化、运维指令等。

5万+

被折叠的 条评论
为什么被折叠?



