MQTT 3.1协议非严肃反思录

前言

MQTT 3.1协议在弱网络环境下(比如2G/3G等)表现不够好,因此才有了反思。

弱网环境下表现

手机等终端在弱网络环境下丢包情况会非常明显,连接MQTT Server成功率很低。相比单纯的请求-相应模型的HTTP,其成功率会比MQTT订阅成功高很多。

手机终端在每次TCP断开或断网后,会即刻发起TCP重连,连接成功,会重复以前步骤依次发送连接命令(CONNECT),订阅命令(SUBSCRIBLE),表明上看,这些过程没有任何问题,但问题就在于从终端成功建立到服务器的连接,到发送订阅命令,在弱网情况下,这个过程将会变得很昂贵:

从TCP建立开始的三次握手到完整的订阅命令发送完毕,考虑到TCP堆栈的每次接收数据方响应ACK,这中间终端和服务器端至少产生了10次数据交互。

在网络变化频繁或者不太稳定的2G/3G网络环境下,这种过程显得有些冗长和不适应,同时会加重已经不堪的弱网络负载的负担。

弱网下,在任何一个阶段的执行过程中,都有可能产生突发性的网络中断的问题:

  1. 无法成功建立TCP链接,或死在三次握手期间,或数据包丢失在握手之后,或客户端连接超时过小
  2. 建立连接后,发送CONNECT命令后,或没接收到TCP ACK确认包,或客户端等待延时太小,导致订阅命令交互失败
  3. 发送SUBSCRIBLE命令后,但服务器端没收到,或因为丢包,或网络已断开,导致发送SUBSCRIBLE命令失败
  4. 成功发送SUBSCRIBLE命令后,或移动网络断开了(有些运营商针对认为HTTP的请求有超时判断),或等待超时,导致订阅失败

TCP是无感知的虚拟连接,中间断开两端不会立刻得到通知,否则就用不着心跳保活机制了。

举一个例子,线上的服务器根据日志分析,只接收到连接命令(CONNECT)但没有后续的订阅命令(SUBSCRIBLE)的情况,每天有上百万级别的数量。

总之,针对低速率弱网络环境,MQTT表现不怎么好。

改进点

业务改进点:

  1. 客户端的连接超时、等待超时设大一点,两秒太短,可设置长一些,比如10秒
  2. 服务器端支持在接收到用户发送CONNECT命令后,瞬间发送一些live data/hot data(早已缓存的数据),类似于HTTP请求-相应模型,目的嘛,一些热数据发送给终端要趁早,越快越好(所谓出名要趁早嘛);这个需要客户端、服务器端同时支持

协议改进点:

  1. CONNECT命令可变头部包含"MQisdp"太多余了,学院派风格嘛
  2. 允许在连接命令中负载(payload)中携带订阅Topic字符串
  3. 允许在连接命令中表示上次连接订阅的Topic发生变化否,携带订阅业务,虽冗余,但实用。 eg:订阅的Topic没有发生变化,TOPICCHANGE:0;退订,UNSUBSCRIBE:TOPICONE;SUBSCRIBE:TOPIC_TWO
  4. PUBLISH、PUBACK等支持的 Message Identifier 才16位,太短,实际业务无法做到全局唯一。引入mid和业务id的映射对应关系?那是状态,需要维护,代价还是蛮高的。业界流行看法,无状态化的架构才是便于横向、竖向、纵向、四方向的扩展,呵呵。最好方式就是修改使之支持字符串形式,否则维护代价高!
  5. 心跳命令PINGREQ/PINGREQ可以做到一个字节传输,节省一个字节,有些强迫症的感觉嘛
  6. 低速率网络需要做一些兼容和调整

有些建议看似冗余,批量或打包处理总比单个处理更高效一些、更节省资源,弱网络环境要求交互要尽可能的少,数据嘛要的是瞬间抵达,越快越好。

严格的分层和业务解耦,会导致性能问题。好比当前Linux内核的TCP/IP网络堆栈分层很清晰,每一层都各司其职,但和直接略过内核态直接运行在用户态(User Space)的Packet I/O相比,处理性能不是在一个档次上,比如Netmap 、DPDK等。

MQTT-SN

针对没有TCP/IP等网络堆栈支持的终端环境,MQTT爱莫能助了。

在一些类似于传感器电子元件中,资源十分受限,计算能力不足,嵌入TCP/IP网络堆栈不现实,比较好的方式基于IEEE 802.15.4用于低速无线个人域网(LR-WPAN)的物理层和媒体接入控制层规范之上发送UDP数据包,每一个数据包最大128个字节。

MQTT-SN(MQTT For Sensor Networks)协议就是为了非常受限类似传感器而设的,协议流程架构比较有趣:

更多协议细节,有待进一步阅读。

TCP不是最适合的移动网络传输协议

先来算一下网络传输的字节数。

以太网帧头至少18个字节,IP头固定20个字节,TCP头20个字节(UDP头部8个字节),再加上电信宽带计费的PPPoE的8个字节:

  • TCP数据包头部信息至少占有66个字节
  • UDP数据报头部信息至少占有54个字节

UDP可以比TCP节省12个字节。

MQTT-SN协议选择使用UDP,可以看出其在节省资源方面的努力。

再看看弱网环境。

  • 在网络可达情况下,UDP可以在TCP建立第一次握手期间就已经把数据送达目的地
  • 完成三次握手期间,UDP客户端和UDP服务器在数据层面可以完成一次完整的交互(PING-PONG)

在网络不好的情况下,UDP的时效性会好于TCP,TCP长连接中间交换过多、使之建立完整交互的过程成功率就很低。此种情况UDP的低延迟和实时性呈现的结果会表现的很突出。

TCP或HTTP理论上是可靠连接,但是在网络不好的时候,也不是那么可靠。客户端一般提交HTTP请求之后,没有确认是否提交成功,在弱网环境下会产生丢包,服务器端嘛收不到。另TCP网络堆栈会存在数据包重发机制 + 应用层重发请求,可能会导致内核处理多次数据包的重发(还有拥塞窗口会收缩,发包速度减慢),可能会加重弱网络的负载。

和TCP相比,UDP的无连接,代表了它快速,资源消耗小,突出表现就是延迟较小。至于数据包丢失没有重传,上层的业务层面应用协议/机制可以确保丢失的数据包重发或补发等,并且会更透明,安全的控性权。而TCP的包重发,上层应用没有控制权限。

连接协议方面:

  • TCP面向连接会产生状态管理和维护,成本不小,比如经常看到的客户端reset异常等。一次完整的请求周期必须固定在一台服务器上
  • UDP无连接的特性。每次请求的数据包可以随机分配到不同的机器上进行处理,可以做到完全无状态化横向扩展

总之,要实时性特诊,或者快速抵达终端的特性,不妨考虑一下UDP。不过呢,很多时候UDP和TCP大家会混合着使用,会互相弥补其不足。

小结

若MQTT协议不能够满足业务需求,或许可考虑选择定制,或简化流程,或使用UDP重新实现,或者使用TCP/HTTP作为补充等,不一而足。

时间: 2024-08-13 16:15:45

MQTT 3.1协议非严肃反思录的相关文章

反思录——工作感受

其实说实话,今天是我由此以来.真正在成长,成熟的,不断经历历练的过程.很多人都说,你的第一份工作如此如此重要.其实未必.第一份工作重不重要而在于你怎么看待这份工作.我也知道,目前大家的处境都很艰难.公司的产品卖不掉,还未实现盈利.老板也在愁,员工也在愁.老板的信任也存在各种危机.小伙伴们在群里从此也不再热闹,大家都讨论着下一步该如何如何.面临那么多问题,大家可能都埋怨老板没有眼光.自己很后悔,怎么选择了这种破公司. 或者还有很多人开始说,我随时被公司辞退,我不能转正.老板就是拖着不让我转正,可以

反思录

转眼之间,我已经到了而立之年的年龄了,这些年经历了很多事情,自己成熟了很多,但是本性依旧未改,我依旧还是那个我,而不是脱胎换骨的我. 人也是自然界中的一种动物,本性中就存在各种各样的弱点.普通人与成功的人的差别就在于是否能够克服掉弱点.我是个人,因此我亦有很多毛病,这些毛病让我犯了很多致命性的错误,让我失去了很多机会.我痛恨自己,痛恨自己一而再,再而三的犯同样的愚蠢的错误.如果我改不了我身上的这些毛病,我将一辈子一事无成,一辈子将平庸的度过.我的家人和孩子将因为我而摆脱不了当前的处境. 我曾经狂

MQTT协议

简介: MQTT协议(Message Queuing Telemetry Transport),翻译过来就是遥信消息队列传输,是IBM公司于1999年提出的,现在最新版本是3.1.1.MQTT是一个基于TCP的发布订阅协议,设计的初始目的是为了极有限的内存设备和网络带宽很低的网络不可靠的通信,非常适合物联网通信. MQTT的网络层级 工作原理: 发布订阅示意图 如上图所示,客户端A连接到消息代理(message broker),消息代理返回确认消息.客户B发布消息温度25度,客户A订阅‘温度’,

工业物联网的云端协议将以MQTT+SSL/TLS为主,协议格式以JSON为主

工业物联网是什么? 简单来说,就是物联网在工业控制上的具体应用. SSL/TLS是什么? SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议.TLS与SSL在传输层对网络连接进行加密.大部分互联网登录都是用的SSL/TLS,可以去网易邮箱http://WWW.126.COM看下,右下角上面"正使用SSL登录"的标识. MQTT是什么? MQTT(M

MQTT是IBM开发的一个即时通讯协议,构建于TCP/IP协议上,是物联网IoT的订阅协议,借助消息推送功能,可以更好地实现远程控制

最近一直做物联网方面的开发,以下内容关于使用MQTT过程中遇到问题的记录以及需要掌握的机制原理,主要讲解理论. 背景 MQTT是IBM开发的一个即时通讯协议.MQTT构建于TCP/IP协议上,面向M2M和物联网IoT的连接协议,采用轻量级发布和订阅消息传输机制.Mosquitto是一款实现了 MQTT v3.1 协议的开源消息代理软件,提供轻量级的,支持发布/订阅的的消息推送模式,使设备对设备之间的短消息通信简单易用. 基本概念 [MQTT协议特点]——相比于RESTful架构的物联网系统,MQ

MQTT学习笔记——MQTT协议体验 Mosquitto安装和使用

0 前言 MQTT是IBM开发的一个即时通讯协议.MQTT是面向M2M和物联网的连接协议,采用轻量级发布和订阅消息传输机制.Mosquitto是一款实现了 MQTT v3.1 协议的开源消息代理软件,提供轻量级的,支持发布/订阅的的消息推送模式,使设备对设备之间的短消息通信简单易用. 若初次接触MQTT协议,可先理解以下概念: [MQTT协议特点]--相比于RESTful架构的物联网系统,MQTT协议借助消息推送功能,可以更好地实现远程控制. [MQTT协议角色]--在RESTful架构的物联网

MQTT协议笔记之连接和心跳

前言 本篇会把连接(CONNECT).心跳(PINGREQ/PINGRESP).确认(CONNACK).断开连接(DISCONNECT)和在一起. CONNECT 像前面所说,MQTT有关字符串部分采用的修改版的UTF-8编码,CONNECT可变头部中协议名称.消息体都是采用修改版的UTF-8编码.前面基本上可变头部内容不多,下面是一个较为完整的CONNECT消息结构:   Description 7 6 5 4 3 2 1 0 Fixed header/固定头部     Message Typ

MQTT协议笔记之消息流

前言 前面的笔记已把所有消息类型都过了一遍,这里从消息流的角度尝试解读一下. 网络故障 在任何网络环境下,都会出现一方连接失败,比如离开公司大门那一刻没有了WIFI信号.但持续连接的另一端-服务器可能不能立即知道对方已断开.类似网络异常情况,都有可能在消息发送的过程中出现,消息发送出去,就丢失了. MQTT协议假定客户端和服务器端稳定情况一般,彼此之通信管道不可靠,一旦客户端网络断开,情况就会很严重,很难恢复原状. 但别忘记,很多客户端会有永久性存储设备支持,比如闪存ROM.存储卡等,在通信出现

TCP/IP, WebSocket 和 MQTT

按照OSI网络分层模型,IP是网络层协议,TCP是传输层协议,而HTTP和MQTT是应用层的协议.在这三者之间, TCP是HTTP和MQTT底层的协议.大家对HTTP很熟悉,这里简要介绍下MQTT.MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分.该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器的通信协议. HTTP的不足 HTTP协议经过多年的使用,发现了