MQTT(消息队列)简介

MQTT(MQ Telemetry Transport)是IBM开发的一种网络应用层的协议,提供轻量级的,支持可发布/可订阅的的消息推送模式,使设备对设备之间的短消息通信变得简单,比如现在应用广泛的低功耗传感器,手机、嵌入式计算机、微型控制器等移动设备。
常用的有eclipse paho、activeMQ、阿里MQTT和其他的实现。

使用场景

  1. 不可靠、网络带宽小的网络
  2. 运行的设备CPU、内存非常有限

特点

  1. 基于发布/订阅模型的协议
  2. 他是二进制协议(协议头只有2个字节),二进制的特点就是紧凑、占用空间小
  3. 提供了三种消息可能性保障(Qos):
    • 0:最多一次
    • 1:最少一次
    • 2:只有一次

以Qos=2(保证消息可达)为例介绍,客户端一条消息发送到服务端需要交互4次: MQTT 轻量级通讯协议 - 图1

关键字术语

  1. HOST:搭载MQTT的服务器地址
  2. TOPIC:消息主题,可以被客户端订阅,实现对应消息的收发
  3. clientId:客户端ID,用于服务器对不同客户端的识别
  4. subscribe/unsubscribe:客户端对消息主题的订阅和取消订阅
  5. Qos:消息的服务质量,当网络过载或拥塞时,QoS 能确保重要业务量不受延迟或丢弃
  6. Callback:当客户端收到消息后对消息的处理(回调)
  7. KeepAliveInterval:客户端与服务器之间的连接是通过发送心跳包来保持存活

自建服务器

EMQ

下载emq开源软件
image.png

  1. # 下载程序包
  2. wget https://www.emqx.io/downloads/broker/v4.0.5/emqx-centos7-v4.0.5.zip
  3. # 解压
  4. unzip emqx-centos7-v4.0.5.zip

运行程序

  1. cd emqx
  2. # 打开程序命令行终端
  3. ./bin/emqx console

image.png
此时服务已经开启,CTRL+ C 关闭终端。也可以使用守护进程模式启动

  1. ./bin/emqttd start

启动错误日志将输出在 log/ 目录。EMQ 消息服务器进程状态查询:

  1. ./bin/emqttd_ctl status

使用ECS服务器开放端口

需要开放以下端口:
image.png
或者使用nginx代理。

授权方式

使用mysql、pgsql等数据库校验方式。请参考:mysql认证

Apache-apollo

Apollo是ActiveMQ的子工程,是ActiveMQ的下一代消息代理。

Apollo 是一个更快、更可靠、更容易维护的消息代理,它是由最初的ActiveMQ的基础构建的。它使用一个完全不同的线程和消息调度架构来实现这一点。与ActiveMQ一样,apollo 是一个多协议代理,支持STOMP、AMQP、MQTT、Openwire、SSL和WebSockets。

MQTT 通配符

⚠️:MQTT允许使用通配符订阅主题,但是并不允许使用通配符广播。 原文 Appendix A - Topic wildcards

一个订阅可能包含特殊字符,允许你一次定义多个主题。
主题层次分隔符被用来在主题中引入层次。多层的通配符和单层通配符可以被使用,但他们不能被使用来做发布者的消息。

主题层级分隔符/

/ 被用来分割主题树的每一层,并给主题空间提供分等级的结构。当两个通配符在一个主题中出现的时候,主题层次分隔符的使用是很重要的。

多层通配符#

# 是一个匹配主题中任意层次数的通配符。比如说,如果你订阅了finance/stock/ibm/#,你就可以接收到以下这些主题的消息。

  1. finance/stock/ibm
  2. finance/stock/ibm/closingprice
  3. finance/stock/ibm/currentprice

多层通配符有可以表示大于等于0的层次。因此,finance/#也可以匹配到单独的finance,在这种情况下#代表0层。在这种语境下主题层次分隔符/就没有意义了。因为没有可以分的层次。
多层通配符只可以确定当前层或者下一层。因此,#finance/#都是有效的,但是finance#不是有效的。多层通配符一定要是主题树的最后一个字符。比如说,finance/#是有效的,但是finance/#/closingprice是无效的。

单层通配符+

+ 只匹配主题的一层。比如说,finance/stock/+匹配finance/stock/ibmfinance/stock/xyz,但是不匹配finance/stock/ibm/closingprice。另外,因为单层通配符只匹配1层,finance/+不匹配finance
单层通配符可以被用于主题树的任意层级,连带多层通配符。它必须被用在主题层级分隔符/的右边,除非它是指定自己。因此,+finance/+都是有效的,但是finance+无效。单层通配符可以用在主题树的末端,也可以用在中间。比如说,finance/+finance/+/ibm都是有效的。

主题语法和用法

当你建立一个应用,设计主题树的时候应该考虑以下的主题名字的语法和语义:

  • 主题至少有一个字符长。
  • 主题名字是大小写敏感的。比如说,Accounts和accounts是两个不同的主题。
  • 主题名字可以包含空格。比如,Accounts payable是一个有效的主题。
  • /开头会产生一个不同的主题。比如说,/finnacefinance不同。/finance匹配"+/+"/+,但不匹配+
  • 不要在任何主题中包含null(Unicode \x0000)字符。

以下的原则应用于主题树的建造和内容

  • 在主题树中,长度被限制于64k内但是在这以内没有限制层级的数目 。
  • 可以有任意数目的根节点,也就是说,可以有任意数目的主题树。

疑难杂症

订阅即收到固定推送

在某次推送时选择了retain模式,以后只要是订阅了该主题,就会按照retain模式下最后一次发送的内容进行推送。

解决方式1:再使用retain模式发送一条空数据

image.png

解决方式2:订阅时设置Retained为false