MQTT主题是MQTT客户端和代理之间进行通信的关键。

根据主题可以对消息进行有效的过滤和路由。

与消息队列相比,MQTT主题非常轻量。

客户端在发布或订阅所需的主题之前不需要创建该主题。代理接受每个有效的主题,而不需要事先进行任何初始化。

介绍

MQTT主题是一个由一个或多个级别组成的UTF-8格式的字符串,中间用斜杠“/”分隔,用于为已连接的客户端过滤消息。

主题规则

  1. 至少一个字符。
  2. 可以包含空格
  3. 区分大小写。
  4. 单独的“/”也是一个有效的主题,可以表示一个具体的主题,也可以用与表示为多个主题的通配符。

以下每行都是一条合规的主题示例:

  1. myhome/groundfloor/livingroom/temperature
  2. USA/California/San Francisco/Silicon Valley

通配符

MQTT客户端订阅主题时,可以订阅已发布消息的确切主题,也可以使用通配符扩大订阅范围。

通配符只能用于订阅,不能用于发布消息

通配符有两种类型:单级和多级。

单级通配符+

MQTT客户端订阅带有单级通配符的主题时,代理会匹配在单级通配符级别处为任意字符串的主题。

多级通配符#

多级通配符由#表示,必须位于主题的最后一个字符,前面必须有一个/

MQTT客户端使用多级通配符订阅主题时,代理会匹配该通配符之前的主题字段,通配符之后的主题字段可以是任意值。

如果MQTT客户端订阅的主题单独指定为#,则客户端将接收发送到代理的所有消息。

使用通配符订阅主题可能会导致向客户端发送大量消息,进而影响系统性能和带宽使用。

以$开头

以$开头的主题用于MQTT代理对外提供内部统计信息

使用通配符#定于主题时,不会包含$开头的主题。

不允许客户端将消息发布到以$开头的主题。

这种类型的主题还没有标准化,目前通常使用$SYS/作为前缀,具体实现由具体的MQTT代理决定。

以$开头的主题分为3种,分别是:

主题类型说明
静态主题(Static Topics)静态主题上的消息仅会在订阅时发布一次。
必选主题(Required Topics)每个MQTT代理都支持的主题。
可选主题(Optional Topics)由具体的MQTT代理决定是否支持的主题。

下面是一些$SYS主题示例

主题类型说明
$SYS/broker/version静态主题、必选主题返回MQTT代理的版本号
$SYS/broker/load/bytes/received必选主题MQTT代理启动以来的接收到的字节数,定时发布
$SYS/broker/load/bytes/sent必选主题MQTT代理启动以来发送的字节数,定时发布

详见SYS Topics · mqtt/mqtt.org Wiki · GitHub

使用建议

避免使用以/开头的主题

虽然以/开头的主题是合规的,但是相当于引入了一个额外的主题级别。

不要在主题中使用非打印编码

尽量不要使用空白字符,增加的可读性远远抵不上增加的问题排查难度(UTF-8种有很多表示空白的字符)。

尽量保持主题简单明确

每条消息都会包含主题,因此为了节省网络流量,尽量使主题简洁明确。

可以在主题中嵌入唯一标识

可以通过在主题中嵌入客户端的相关信息,比如ClientID或用户名等,用于确认消息发送者以及控制发布权限等。

避免订阅通配符(#)

在吞吐量很大的环境中,订阅通配符#会导致MQTT客户端收到大量消息负载,增加客户端的处理难度,以及资源消耗。

主题尽量明确

可以使用主题反映特定的数据,避免对多种类型的消息使用单个主题。

例如,客厅里有三个传感器,可以创建主题如myhome/livingroom/temperature,myhome/livingroom/brightness,myhome/living room/humidity分别用来获取温度、亮度以及湿度数据,而不是使用统一的主题如myhome/livingroom

这种方式能够提高数据辨识度,也可以更好的使用MQTT的高级特性,比如保留消息。