利用 Hub 服务进行设备间消息转发
声明:
- 本文测试所用设备系统为 Ubuntu 18.04
- 模拟 MQTT client 行为的客户端为 MQTTBox提示:Darwin 系统可以通过源码安装 Baetyl,可参考 源码编译 Baetyl。
与 连接测试 不同的是,若需要通过 Hub 服务完成消息在设备间的转发及简单路由,除需要配置连接项信息外,还需要给可允许连接的 client 配置相应主题的权限,及简单的消息路由策略,完整的配置参考 Hub 服务配置。
本文以 TCP 连接方式为例,测试 Hub 服务的消息路由、转发功能。
操作流程
- 步骤一:安装 Baetyl,并导入示例配置包。参考 快速安装 Baetyl 进行操作;
- 步骤二:依据测试需求修改导入的配置信息,执行
sudo systemctl start baetyl
以容器模式启动 Baetyl,然后执行sudo systemctl status baetyl
来查看 Baetyl 是否正常运行。如果 Baetyl 已经启动,执行sudo systemctl start baetyl
重启来加载新的配置。 - 步骤三:通过 MQTTBox 以 TCP 方式与 Hub 服务建立连接;
- 若成功与 Hub 服务建立连接,则依据配置的主题权限信息向有权限的主题发布消息,同时向拥有订阅权限的主题订阅消息;
- 若与 Hub 服务建立连接失败,则重复
步骤三
操作,直至 MQTTBox 与 Hub 服务成功建立连接为止。
- 步骤四:通过 MQTTBox 查看消息的收发状态。
消息路由测试
Baetyl 应用配置替换成如下配置:
- # /usr/local/var/db/baetyl/application.yml
- version: V2
- services:
- - name: hub
- image: 'hub.baidubce.com/baetyl/baetyl-hub'
- replica: 1
- ports:
- - '1883:1883'
- mounts:
- - name: localhub-conf
- path: etc/baetyl
- readonly: true
- - name: localhub_data
- path: var/db/baetyl/data
- - name: log-V1
- path: var/log/baetyl
- volumes:
- - name: localhub-conf
- path: var/db/baetyl/localhub-conf/V1
- - name: log-V1
- path: var/db/baetyl/log
- - name: localhub_data
- path: var/db/baetyl/localhub_data
Baetyl Hub 服务配置替换成如下配置:
- # /usr/local/var/db/baetyl/localhub-conf/service.yml
- listen:
- - tcp://0.0.0.0:1883
- principals:
- - username: 'test'
- password: 'hahaha'
- permissions:
- - action: 'pub'
- permit: ['#']
- - action: 'sub'
- permit: ['#']
- subscriptions:
- - source:
- topic: 't'
- target:
- topic: 't/topic'
- logger:
- path: var/log/baetyl/service.log
- level: 'debug'
如上配置,消息路由依赖 subscriptions
配置项,这里表示发布到主题 t
的消息将会转发给所有订阅主题 t/topic
的设备(用户)。
注意:上述配置项信息中,permissions
项下属 action
的 permit
权限主题列表支持 +
和 #
通配符配置,其具体释义如下详述。
#
匹配策略
对于 MQTT 协议,数字标志(#
U+0023)是用于匹配主题中任意层级的通配符。多层通配符表示它的父级和任意数量的子层级。多层通配符必须位于它自己的层级或者跟在主题层级分隔符(/
U+002F)后面。不管哪种情况,它都必须是主题过滤器的最后一个字符。
例如,如果客户端订阅主题 sport/tennis/player1/#
,它会收到使用下列主题名发布的消息:
sport/tennis/player1
sport/tennis/player1/ranking
sport/tennis/player1/score/wimbledon
此外,主题sport/#
也匹配单独的sport
,因为#
包括它的父级。
对于 Baetyl 来说,如果在 permit
配置项中配置了主题 #
(不论是发布行为,还是订阅行为),都不需要再额外配置其他的主题。这时,配置项中的账户(依据 username/password
)拥有向所有合法的 MQTT 协议主题发布或订阅的权限。
+
匹配策略
对于 MQTT 协议,加号(+
U+002B) 是只能用于单个主题层级匹配的通配符。在主题过滤器的任意层级都可以使用单层通配符,包括第一个和最后一个层级。然而它必须占据过滤器的整个层级。可以在主题过滤器中的多个层级中使用它,也可以和多层通配符一起使用。
例如,主题 sport/tennis/+
匹配 sport/tennis/player1
和 sport/tennis/player2
,但是不匹配 sport/tennis/player1/ranking
。同时,由于单层通配符只能匹配一个层级,sport/+
不匹配 sport
但是却匹配 sport/
。
对于 Baetyl 来说,如果在 permit
配置项中配置了主题 +
(不论是发布行为,还是订阅行为),都不需要再额外配置其他的单层主题。这时,配置项中的账户(依据 username/password
)拥有向所有合法的 MQTT 协议单层主题发布或订阅的权限。
提示:在 MQTT 协议中,通配符(不论是多层通配符 #
,还是单层通配符 +
)只能出现在订阅的主题过滤器中,而不准出现在发布的主题中。但是,为了增强主题权限配置的灵活性,Baetyl 在设计中认定,通配符不论出现在订阅行为的主题配置项中,还是出现在发布行为的主题配置项中,都是合法的。这里,在进行具体的发布/订阅行为时,发布或订阅的主题只要符合 MQTT 协议的要求即可。特别地,对于需要在 principals
配置项中配置大量发布和订阅主题的开发者来说,推荐采用通配符( #
和 +
)策略。
设备间消息转发路由测试
设备间消息转发、路由流程具体如下图示:
设备间消息转发路由流程图
具体地,如上图所示,client1、client2 及 client3 分别与 Hub 服务建立连接关系,client1 具备向主题 t
发布消息的权限,client2 及 client3 分别拥有向主题 t
及 t/topic
订阅消息的权限。
一旦上述三个 client 与 Hub 服务的连接关系建立后,依照上文 subscriptions 配置项信息,client2 及 client3 将会分别得到从 client1 向 Baetyl Hub 服务发布到主题 t
的消息。
特别地,client1、client2 及 client3 可以合并为一个 client,则新的 client 即拥有向主题 t
的发布消息权限,又拥有向主题 t
及 t/topic
订阅消息的权限。这里,采用 MQTTBox 作为该新 client,点击 Add subscriber
按钮添加主题 t
及 t/topic
进行订阅。
然后点击 Publish
按钮向 Hub 服务发送主题为 t
负载为 This is a new message.
的消息,即会发现在订阅的主题 t
及 t/topic
中均收到了该消息,详细如下图示。
MQTTBox 成功收到消息
综上,即通过 MQTTBox 完成了基于 Hub 服务的设备间消息转发、路由测试。