zoukankan      html  css  js  c++  java
  • MQTT V3.1----flow

    该文章转自:聂永的博客(http://www.blogjava.net/yongboy/archive/2014/02/15/409893.html)


     

    网络故障

    在任何网络环境下,都会出现一方连接失败,比如离开公司大门那一刻没有了WIFI信号。但持续连接的另一端-服务器可能不能立即知道对方已断开。类似网络异常情况,都有可能在消息发送的过程中出现,消息发送出去,就丢失了。

    MQTT协议假定客户端和服务器端稳定情况一般,彼此之通信管道不可靠,一旦客户端网络断开,情况就会很严重,很难恢复原状。

    但别忘记,很多客户端会有永久性存储设备支持,比如闪存ROM、存储卡等,在通信出现异常的情况下可以用于保存关键数据或状态信息等。

    总之,异常网络情况很复杂,只能小心处理之。

    消息重发策略

    QoS > 0情况下,PUBLISH、PUBREL、SUBSCRIBE、UNSUBSCRIBE等类型消息在发送者发送完之后,需要等待一个响应消息,若在一个指定时间段内没有收到,发送者可能需要重试。重发的消息,要求DUP标记要设置为1.

    等待响应的超时应该在消息成功发送之后开始算起,并且等待超时应该是可以配置选项,以便在下一次重试的时候,适当加大。比如第一次重试超时10秒,下一次可能为20秒,再一次重试可能为60秒呢。当然,还要有一个重试次数限制的。

    还 有一种情况,客户端重新连接,但未在可变头部中设置clean session标记,但双方(客户端和服务器端)都应该重试先前未发送的动态消息(in-flight messages)。客户端不被强制要求发送未被确认的消息,但服务器端就得需要重发那些未被去确认的消息。

    QoS level决定的消息流

    QoS level为Quality of Service level的缩写,翻译成中文,服务质量等级。

    MQTT 3.1协议在"4.1 Quality of Service levels and flows"章节中,仅仅讨论了客户端到服务器的发布流程,不太完整。因为决定消息到达率,能够提升发送质量的,应该是服务器发布PUBLISH消息到订阅者这一消息流方向。

    QoS level 0

    至多发送一次,发送即丢弃。没有确认消息,也不知道对方是否收到。

    Client

    Server
    QoS = 0 PUBLISH
    ---------->
    Action: Publish message to subscribers then Forget
    Reception: <=1

    针对的消息不重要,丢失也无所谓。

    网络层面,传输压力小。

    QoS level 1

    所有QoS level 1都要在可变头部中附加一个16位的消息ID。

    SUBSCRIBE和UNSUBSCRIBE消息使用QoS level 1。

    针对消息的发布,Qos level 1,意味着消息至少被传输一次。

    发送者若在一段时间内接收不到PUBACK消息,发送者需要打开DUB标记为1,然后重新发送PUBLISH消息。因此会导致接收方可能会收到两次PUBLISH消息。针对客户端发布消息到服务器的消息流:

    Client

    Server
    QoS = 1
    DUP = 0
    Message ID = x

    Action: Store message

    PUBLISH
    ---------->
    Actions:
    • Store message

    • Publish message to subscribers
    • Delete message

    Reception: >=1
    Action: Discard message PUBACK
    <----------
    Message ID = x

    针对服务器发布到订阅者的消息流:

    Server

    Subscriber
    QoS = 1
    DUP = 0
    Message ID = x
    PUBLISH
    ---------->
    Actions:
    • Store message

    • Make message available                       
    Reception: >=1
      PUBACK
    <----------
    Message ID = x

    发 布者(客户端/服务器)若因种种异常接收不到PUBACK消息,会再次重新发送PUBLISH消息,同时设置DUP标记为1。接收者以服务器为例,这可能 会导致服务器收到重复消息,按照流程,broker(服务器)发布消息到订阅者(会导致订阅者接收到重复消息),然后发送一条PUBACK确认消息到发布 者。

    在业务层面,或许可以弥补MQTT协议的不足之处:重试的消息ID一定要一致接收方一定判断当前接收的消息ID是否已经接受过

    但一样不能够完全确保,消息一定到达了。

    QoS level 2

    仅仅在PUBLISH类型消息中出现,要求在可变头部中要附加消息ID。

    级别高,通信压力稍大些,但确保了仅仅传输接收一次。

    先看协议中流程图,Client -> Server方向,会有一个总体印象:

    Client

    Server
    QoS = 2
    DUP = 0
    Message ID = x

    Action: Store message

    PUBLISH
    ---------->
    Action(a) Store message

    or

    Actions(b):
    • Store message ID
    • Publish message to subscribers
      PUBREC
    <----------
    Message ID = x
    Message ID = x PUBREL
    ---------->
    Actions(a):
    • Publish message to subscribers
    • Delete message

    or

    Action(b): Delete message ID
    Action: Discard message PUBCOMP
    <----------
    Message ID = x

    Server -> Subscriber

    Server

    Subscriber
    QoS = 2
    DUP = 0
    Message ID = x
    PUBLISH
    ---------->
    Action: Store message
      PUBREC
    <----------
    Message ID = x
    Message ID = x PUBREL
    ---------->
    Actions:
    • Make message available                       
      PUBCOMP
    <----------
    Message ID = x

    Server 端采取的方案a和b,都包含了何时消息有效,何时处理消息。两个方案二选一,Server端自己决定。但无论死采取哪一种方式,都是在QoS level 2协议范畴下,不受影响。若一方没有接收到对应的确认消息,会从最近一次需要确认的消息重试,以便整个(QoS level 2)流程打通。

    消息顺序

    消息顺序会受许多因素的影响,但对于服务器程序,必须保证消息传递流程的每个阶段要和开始的顺序一致。例如,在QoS level 2定义的消息流中,PUBREL流必须和PUBLISH流具有相同的顺序发送:

    Client

    Server
      PUBLISH 1
    ---------->
    PUBLISH 2
    ---------->
    PUBLISH 3
    ---------->
     
      PUBREC 1
    <----------
    PUBREC 2
    <----------
     
      PUBREL 1
    ---------->
     
      PUBREC 3
    <----------
     
      PUBREL 2
    ---------->
     
      PUBCOMP 1
    <----------
     
      PUBREL 3
    ---------->
     
      PUBCOMP 2
    <----------
    PUBCOMP 3
    <----------
     

    流动消息(in-flight messages)数量允许有一个可保证的效果:

    • 在流动消息(in-flight)窗口1中,每个传递流在下一个流开始之前完成。这保证消息以提交的顺序传递
    • 在流动消息(in-flight)大于1的窗口,只能在QoS level内被保证消息的顺序

    消息的持久化

    在MQTT协议中,PUBLISH消息固定头部RETAIN标记,只有为1才要求服务器需要持久保存此消息,除非新的PUBLISH覆盖。

    对于持久的、最新一条PUBLISH消息,服务器不但要发送给当前的订阅者,并且新的订阅者(new subscriber,同样需要订阅了此消息对应的Topic name)会马上得到推送。

    Tip:新来乍到的订阅者,只会取出最新的一个RETAIN flag = 1的消息推送,不是所有。
    

    小结

    mqtt的消息流,以小和轻量为主要目标,QoS级别进行了消息传输的保证。

  • 相关阅读:
    SP笔记:交叉实现七行并成一行
    HTML tag 学习
    操作哈希表
    Efficient bipedal robots based on passivedynamic walkers
    Pushing People Around
    ZEROMOMENT PONTTHIRTY FIVE YEARS OF ITS LIFE

    Active Learning for RealTime Motion Controllers
    Accelerometerbased User Interfaces for the Control of a Physically Simulated Character
    Dynamic Response for Motion Capture Animation
  • 原文地址:https://www.cnblogs.com/leeying/p/3795896.html
Copyright © 2011-2022 走看看