MQTT 学习笔记

MQTT特点

MQTT协议是为大量计算能力有限,且工作在低带宽、不可靠的网络的远程传感器和控制设备通讯而设计的协议。

1、使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合

2、对负载内容屏蔽的消息传输。

3、使用TCP/IP提供网络连接:

主流的MQTT是基于TCP连接进行数据推送的,但是同样有基于UDP的版本,叫做MQTT-SN。这两种版本由于基于不同的连接方式,优缺点自然也就各有不同了

4、有三种消息发布服务质量:

[1] “至多一次”,消息发布完全依赖底层TCP/IP网络。会发生消息丢失或重复:

这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。这一种方式主要普通APP的推送,倘若你的智能设备在消息推送时未联网,推送过去没收到,再次联网也就收不到了。

[2] “至少一次”,确保消息到达,但消息重复可能会发生:

这一种方式比较鸡肋,在我的想象中没能想到这种质量的发送在常规的APP开发中有什么用处。

[3] “只有一次”,确保消息到达一次:

这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。这种最高质量的消息发布服务还可以用于即时通讯类的APP的推送,确保用户收到且只会收到一次。

5、小型传输,开销很小(固定长度的头部是2字节),协议交换最小化,以降低网络流量:
这就是为什么在介绍里说它非常适合“在物联网领域,传感器与服务器的通信,信息的收集”,要知道嵌入式设备的运算能力和带宽都相对薄弱,使用这种协议来传递消息再适合不过了。
 

6、使用Last Will和Testament特性通知有关各方客户端异常中断的机制:

Last Will:即遗言机制,用于通知同一主题下的其他设备发送遗言的设备已经断开了连接。

Testament:遗嘱机制,功能类似于Last Will 。

 

由于MQTT 协议具有开放、简单、轻量、易于实
现等优点, 因此他特别适用于低带宽, 网络不稳定,
网络代价昂贵以及处理器和存储器资源有限的嵌入式
设备和移动终端上.

术语:

客户端(Client):
使用MQTT的程序或设备。客户端总是通过网络连接到服务端。它可以

  • 发布应用消息给其它相关的客户端。.
  • 订阅以请求接受相关的应用消息
  • 取消订阅以移除接受应用消息的请求。
  • 从服务端断开连接。

服务端(Server):

一个程序或设备,作为发送消息的客户端和请求订阅的客户端之间的中介。服务端

  • 接受来自客户端的网络连接
  • 接受客户端发布的应用消息
  • 处理客户端的订阅和取消订阅请求
  • 转发应用消息给符合条件的客户端订阅

订阅(Subscription):

订阅包含一个主题过滤器(Topic Filter)和一个最大的服务质量(QoS)等级。订阅与单个会话(Session)关联。会话可以包含多于一个的订阅。会话的每个订阅都有一个不同的主题过滤器。

主题名(Topic Name):

附加在应用消息上的一个标签,服务端已知且与订阅匹配。服务端发送应用消息的一个副本给每一个匹配的客户端订阅。

主题过滤器(Topic Filter:):

订阅中包含的一个表达式,用于表示相关的一个或多个主题。主题过滤器可以使用通配符。

会话(Session):

客户端和服务端之间的状态交互。一些会话持续时长与网络连接一样,另一些可以在客户端和服务端的多个连续网络连接间扩展。

控制报文(MQTT Control Packet):

通过网络连接发送的信息数据包。MQTT规范定义了十四种不同类型的控制报文,其中一个(PUBLISH报文)用于传输应用消息。

 

系统框架设计

整个服务器部分主要分成三个层次. 第一层是
MQTT 消息推送broker, 负责完成协议底层的网络通
信机制以及针对各种不同类型消息的收发机制; 第二

层由身份验证模块、ACL 控制模块、自动订阅模块、
话题统计模块以及状态监控模块组成, 是在底层通信
机制的基础上完善整个系统实际应用中所需的各项功
能; 第三层是数据存储层, 为第二层的各个模块提供
数据的支持, 用于各项数据的统计与交互. 整个系统
框架如图1 所示.

各模块的设计与实现

消息推送中间件

目前在各种平台上对于MQTT协议有许多不同的
实现, 这里所选择的Mosquitto 是一款开源的基于C实
现的MQTT server/broker, 比较完整的实现了MQTT
协议中要求的各项基本功能, 可以在Windows, Linux
以及其它类Unix 系统中编译运行.

数据存储层

在数据存储层中, 有的数据是需要经常读取的,
比如用户的名称、密码、ID 以及用户间的好友关系等;
有的数据是需要经常写入和修改的, 比如某些话题的
订阅数; 有的数据是不经常读取或写入的, 比如服务
器的运行状态. 为了提高效率, 对于需要经常读取或
写入的与用户相关的数据, 用Redis 数据库存储, 对于
不经常读取或写入的与服务器状态相关的数据, 用
MYSQL 数据库存储.

这里的Redis 是一个基于key-value 的开源no-sql
数据库, 它将数据缓存在内存中, 相对于传统的关系
型数据库来说, 性能上有很大提高, 特别适用于对访
问速度和并发性要求比较高的情况[6,7]. 同时Redis 也
支持数据的持久化, 并且支持list, set, hash 等多种不同
的数据结构. 在这里采用Redis 来存储每个用户的用
户名密码等相关信息和与话题有关的数量统计, 以处理大并发量下的用户访问请求.

密码验证模块

在客户端向服务器发起连接请求的时候, 服务器
必须对其进行密码验证, 以决定是否接受该连接请求,
验证过程如图2 所示.

为了增加数据库的安全性, 在用户注册时需要对其
密码加密后再将其密文存入数据库, 这样即使有人利用
非法手段侵入数据库, 也无法得到用户的真实密码. 在
这里采用的MD5 加密算法是一种散列加密算法[8], 任何
一个密码经过MD5 的HASH 散列计算之后将会产生一
个128bit 的序列. 但是缺点是两个相同的密码会产生相
同的散列, 为了弥补这个不足, 需要引入SALT 技术[9],
在用户注册时生成一个随机数据, 与用户密码一起进行
散列计算, 然后将得到的密文和SALT 值一起存入数据
库中, 这样就可以保证即使用户的密码相同, 只要随机
的SALT 值不同, 其密文就不相同.
在用户发起连接请求时, 将用户提交的密码明文
与数据库中的SALT 值一起进行散列计算, 将所得密文
与数据库中密文进行比对即可对用户密码进行验证.

ACL 控制模块

为了规范用户行为, 需要对其话题的订阅和发布
进行权限控制. ACL(Access Control List)又称为访问控
制列表, 是一种通过匹配关系对访问权限进行控制,
以加强系统安全性的技术[10,11].
ACL 表采用的格式为:
user <username>
[read/write] <topic>
或者

pattern [read/write] <topic>
第一种格式为特定用户的权限控制规则, 第二种
格式为所有用户的权限控制规则, read 表示具有订阅
的权限, write 表示具有发布的权限, topic 采用层级结
构组织, 检查的时候从左至右各层依次进行匹配.
ACL 表赋予用户应该具有的最小权限, 只要满足表中
的一项, 即表示验证通过.
为了满足移动社交网络中的应用需求, 需要引入
通配符来表示用户之间的关系, 在这里, 用%u 表示用
户自身的用户名, %c 表示用户自身的ID 号, %f 表示用
户的单向关注的关系, %F 表示用户互相关注的关系
(这里我们称之为好友), +表示话题中单层的通配, #表
示话题中若干层的通配, 一个典型的ACL 表项为:
pattern read user/%F/presence/+
该规则表示该用户对所有他的好友的presence 之
下的一级子话题具有订阅的权限.

自动订阅模块

在系统的实际应用中, 用户需要接收各种各样的
推送话题, 例如系统的广播通知、好友的上线提醒、好
友发送的即时消息等, 如果每次上线的时候都由客户
端来对这些话题进行订阅, 不但会影响客户端的性能,
还会占用移动终端的网络资源, 尤其是在用户关系复
杂, 需要订阅大量话题的时候. 因此, 服务器可以在用
户登录成功之后为用户自动订阅这些话题, 以减少网
络上的数据交互. 自动订阅模块流程如图3 所示.

自动订阅支持ACL 控制模块中提到的各项通配
符, 并且将%u 替换为自身用户名, %c 替换为自身ID,
含有%f 和%F 的表项会被通配为多个话题分别进行自
动订阅. 一个典型的自动订阅表项为:
user/%F/presence/+ 1
表示每个用户上线时都会自动订阅其好友的
presence之下一级的话题, QoS设为1, 中间以空格分隔.

话题统计模块

当大量用户在一段时间内同时订阅某一话题, 或
者向某一话题发布消息时, 意味着这个话题是当前用
户所关注的热点. 因此, 对话题的统计有助于分析用
户群体的行为方式以及当前社会生活中的热点时事,
对于发掘用户的潜在需求有重要的意义.
为了提高消息推动服务器的性能, 话题的统计数
据记录在redis 数据库中, 以topic-count 的形式存储,
当用户在统计的话题上进行订阅或者发布的时候, 服
务器调用Redis 的INCR 或DECR 命令对统计数据进
行更新.

状态监控模块

要确保服务器长时间稳定的运行, 需要定期对系
统运行的状态进行监控. 一方面要监控服务器本身的
系统信息, 如CPU 占用率、内存占用率、磁盘剩余空
间大小、网络流量等等, 这些数据在linux 环境下可以
通过解析/proc 下相关文件的内容来获取; 另一方面需
要监控消息推送服务的运行状况, 如活跃的用户数、
用户订阅话题的总数等. Mosquitto 提供了对这些信息
进行统计的机制, 所得的数据将由服务器以话题的形
式定期进行发布, 监控模块需要以客户的身份登录并
订阅相应话题以获取相关信息, 采集到的结果插入到
MYSQL 数据库中, 以供服务器进行性能分析以预警.

原文地址:https://www.cnblogs.com/saryli/p/9748095.html