日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

mqtt 获取所有topic_MQTT协议解析

發(fā)布時(shí)間:2025/4/17 132 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mqtt 获取所有topic_MQTT协议解析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這篇屬于IM三劍客中的第二篇,前面一篇主要講解了通用IM的一些架構(gòu)的知識,這邊主要講解MQTT協(xié)議的細(xì)節(jié),最后一篇將會(huì)著重介紹了MQTT Broker的Go語言實(shí)現(xiàn)。
  • 通用IM架構(gòu)
  • Go實(shí)現(xiàn)Mqtt broker

MQTT協(xié)議以其效率高,語義完善而著名,非常適合使用在移動(dòng)設(shè)備中,可以大幅度的減少耗電量。相對于TCP,語義更加豐富,額外的overload小,最少只需要2byte;相對于其他的應(yīng)用層協(xié)議Websocket等,頭部簡單,包體積更小。

相關(guān)術(shù)語

Client(客戶端)

客戶端通常是用戶手中的移動(dòng)設(shè)備,傳感器等,客戶端在整個(gè)mqtt流程中既有publisher的作用,還有subscriber的作用,當(dāng)作publisher的時(shí)候,客戶端可以進(jìn)行數(shù)據(jù)的上報(bào),作為subscriber的時(shí)候,可以接收服務(wù)端推送的消息。

Session

持久化的回話,一個(gè)session對應(yīng)一個(gè)client,session會(huì)把還未來得及投遞的消息進(jìn)行持久化,以便下次client連接時(shí)進(jìn)行推送。

Broker

服務(wù)器端,client連接的對象,保存有所有的subscriber和publisher信息及其訂閱關(guān)系,同時(shí)也用作消息的分發(fā)功能。

Subscription

訂閱關(guān)系,client可以依據(jù)topic進(jìn)行訂閱,可以接收發(fā)布到該topic的信息。

Topic

Topic用作訂閱關(guān)系的維系,類似于channel的概念。

Topic Filter

主題過濾器,在MQTT中,topic可以是精確訂閱,也可以是模糊訂閱,發(fā)布到一個(gè)topic的消息,通過主題過濾器獲取所有匹配的topic進(jìn)行投遞。

Publisher

發(fā)布者,通常是客戶端,向broker發(fā)布消息,borker收到消息后依據(jù)topic進(jìn)行投遞。

Subscriber

訂閱者,通常是客戶端,訂閱topic以接收broker分發(fā)的消息。

數(shù)據(jù)解包

MQTT數(shù)據(jù)包共分為三部分,FixedHeader, Variable Header 和 Payload, 其中只有FixedHeader是必須的,Variable Header和Payload部分是可選的。這部分著重介紹FixedHeader,可選部分將在下面的詳細(xì)介紹中涉及。

固定頭部的長度為2...5 byte,說到這里,可能有人迷糊了,既然說的是固定頭部,怎么長度還有不同的選項(xiàng)呢。其實(shí)固定頭部的意思并不是說長度固定,而是說每個(gè)數(shù)據(jù)包必須包含的意思,哪怕一個(gè)數(shù)據(jù)包什么內(nèi)容都沒有,也要有一個(gè)長度為2的頭部數(shù)據(jù)。那么長度不固定的固定頭部又該如何解釋呢,因?yàn)椴煌膱鼍皵?shù)據(jù)包的大小也不近相同,為了能讓服務(wù)端知曉如何解析,解析到何處,就必須要把數(shù)據(jù)包的大小給編碼到數(shù)據(jù)包中,數(shù)據(jù)包有大有小,如果用一個(gè)比較小的數(shù)字的話,就無法發(fā)送大于該數(shù)字的數(shù)據(jù)了,如果數(shù)據(jù)包比較小,但是編碼用的數(shù)字又比較大的話,就會(huì)造成浪費(fèi)的現(xiàn)象,所以針對不同大小的數(shù)據(jù),需要用不同的方式對長度進(jìn)行編碼,這就是可變長度的由來。

在mqtt中,數(shù)據(jù)包的大小由第2個(gè)byte到第5個(gè)byte來決定,最小為1個(gè)字節(jié),最大為4個(gè)字節(jié),加上頭部固定的一個(gè)字節(jié),正好是2...5 byte.

下面為FixedHeader的結(jié)構(gòu):

Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0Byte 1MsgTypeMsgTypeMsgTypeMsgTypeDupQosQosRetainedByte 2Has 3?Byte 3Has 4?Byte 4Has 5?Byte 5

第一個(gè)字節(jié)

第一個(gè)字節(jié)主要用做消息類型的控制,以及對應(yīng)消息類型的額外的屬性。按照bit分割,共有8bit,前四個(gè)bit用來表示數(shù)據(jù)包的類型,是connect還是publish,除了0和15外(用作保留類型),其他的14中均有不同的定義,下方分別給出了14中類型的詳細(xì)的解釋。詳細(xì)解釋

剩下的4bit

  • 第一個(gè)bit,是Duplicated的意思,用在publish中qos為1/2的情況,用來表明該消息是否為一條重復(fù)的消息。
  • 第2/3個(gè)bit,聲明了qos的級別,可選的有(0b00, 0b01, 0b10),分別代表了(QOS0, QOS1, QOS2),不能有3,如果是3的話,會(huì)被認(rèn)為成一個(gè)非法的數(shù)據(jù)包。
  • 第四個(gè)bit,Retained,告知broker是否要將消息持久化,以供后來的訂閱者消費(fèi)。

剩下的字節(jié)

這個(gè)部分用來表示剩下的數(shù)據(jù)的長度,前面說了,這個(gè)部分長度是可變的,范圍為1-4,那么如果來確定長度是1還是其他的呢,秘密就藏在字節(jié)的最高位(7bit),這部分的所有數(shù)據(jù),最高位bit都表明有沒有后續(xù)的長度,如果這個(gè)值為0的話,表明沒有后續(xù)的數(shù)據(jù)了,如果是一的話,表明還需要繼續(xù)計(jì)算長度,因此能表明的數(shù)字最小為0,最大為128 * 128 * 128 * 128 = 268435456 byte = 256 Mb。

消息類型

連接與認(rèn)證

Connect(1)

當(dāng)客戶端建立好與服務(wù)器的連接后,客戶端發(fā)送的第一個(gè)報(bào)文必須是Connect,并且只能發(fā)送一次,服務(wù)端在收到第二個(gè)Connect的時(shí)候,會(huì)認(rèn)為客戶端異常而斷開連接。·

Connack(2)

服務(wù)端響應(yīng),

心跳與保活

Pingreq(12)

客戶端發(fā)送,無Variable Header與Payload,

Pingresp(13)

服務(wù)端響應(yīng),無Variable Header與Payload,

訂閱

Subscribe(8)

Suback(9)

取消訂閱

Unsubscribe(10)

Unsuback(11)

發(fā)布消息

Publish(3)

Pubrel(6)

用在QOS2消息的第二階段,

接收消息

Puback(4)

用在QOS1的消息上,當(dāng)收到QOS1的消息后,馬上回復(fù)Puback的消息,同時(shí)設(shè)置MessageId為Publish消息的MessageId,

Pubrec(5)

用在QOS2消息的第一階段

Pubcomp(7)

用在QOS2消息的第二階段

斷開連接

Disconnect(14)

當(dāng)客戶端主動(dòng)斷開連接時(shí),主動(dòng)發(fā)送Disconnect消息,該消息無Varibale Header與Payload。


服務(wù)質(zhì)量保證

MQTT發(fā)布消息QoS保證不是端到端的,是客戶端與服務(wù)器之間的。訂閱者收到MQTT消息的QoS級別,最終取決于發(fā)布消息的QoS和主題訂閱的QoS。

發(fā)布者發(fā)布的Qos訂閱者訂閱的Qos最終的QOS000010020100111121200211222

總而言之,言而總之,最終的QOS級別為兩者中保證較弱的一方的QOS。即 qos = min(qos Publisher, qos Subscriber)

Qos 0

Qos 0只會(huì)投遞一次,沒有任何到達(dá)的保證,數(shù)據(jù)從Publisher到Broker,再從Broker到Subscriber均為一次發(fā)送,適合一些不那么重要的數(shù)據(jù)。

sequenceDiagramparticipant Publisherparticipant Brokerparticipant SubscriberPublisher->>Broker: PublishPublisher->>Publisher: Delete(Msg)Broker->>Subscriber: PublishBroker->>Broker: Delete(Msg)

Qos 1

相對于Qos 0,Qos 1多了一次Ack的機(jī)制,publish->ack,發(fā)布完一條消息后,本地并不會(huì)馬上刪除,而是存儲(chǔ)到一個(gè)inflight隊(duì)列中并等待ack的到來,peer收到qos 1的消息后,馬上進(jìn)行ack操作,同時(shí)將消息提供給上游業(yè)務(wù)來處理,上游業(yè)務(wù)需要自行去重。后續(xù)的處理分為以下幾種情況:

  • 及時(shí)收到ack,刪除本地inflight隊(duì)列中數(shù)據(jù)即可。
  • 未能收到ack,分為以下幾種情況:
    • publish失敗,只需重新發(fā)送即可。
    • ack丟失,重新發(fā)送,服務(wù)端進(jìn)行ack,上游業(yè)務(wù)去重。
對于Qos1/2的消息,通常來說,pending狀態(tài)的消息是有上限的,當(dāng)達(dá)到上限時(shí),可以丟棄掉消息,并且告知本地的上游業(yè)務(wù)。sequenceDiagramparticipant Publisherparticipant Brokerparticipant SubscriberPublisher->>Publisher: Store(Msg)Publisher->>Broker: Publish (msg_id = x)Broker->>Broker: Store(Msg)Broker->>Subscriber: Publish (msg_id = y)Broker->>Publisher: Puback (msg_id = x)Publisher->>Publisher: Delete(Msg)Subscriber->>Broker: Puback (msg_id = y)Broker->>Broker: Delete(Msg)

Qos 2

Qos2,恰好一次是最理想的狀態(tài),然后現(xiàn)實(shí)中因?yàn)楦鞣N各樣的問題,是很難100%實(shí)現(xiàn)的,因此我們就需要各種協(xié)議來盡可能的保證恰好一次的語義,相對于Qos1,Qos2保證了恰好一次,Qos1只能保證至少一次,消息的去重需要上游業(yè)務(wù)處理,Qos2保證丟給上游業(yè)務(wù)的消息也是恰好一次的。

在Qos1中,客戶端需要根據(jù)不同的情況進(jìn)行多次重試,Subscriber一旦收到任何消息后就會(huì)把消息傳遞給上游,在Qos2中,我們希望Publisher可以知道Subscriber已經(jīng)收到消息了,但是先不要投遞給上游的業(yè)務(wù)(一旦投遞給上游后,但Publisher并不知道Subscriber已經(jīng)收到消息了,可能會(huì)造成多次的投遞),因此當(dāng)Subscriber收到消息后,回復(fù)一次我已經(jīng)收到了(Pubrec),Publisher收到回復(fù)后,知道Subscriber已經(jīng)收到消息,接下來告知Subscriber可以把消息提交給上游了(Pubrel),Subscriber收到Pubrel后,將消息提交到上游,并且告知Publisher完成投遞(Pubcomp),Publisher收到消息后,知道投遞完成,刪除本地的消息。

這個(gè)過程有沒有感覺和分布式事務(wù)中的2PC非常類似,第一階段(Prepare),第二階段(Commit)。

sequenceDiagramparticipant Publisherparticipant Brokerparticipant SubscriberPublisher->>Publisher: Store(Msg)Publisher->>Broker: PublishBroker->>Broker: Store(Msg)Broker->>Publisher: PubrecPublisher->>Broker: PubrelBroker->>Subscriber: PublishBroker->>Publisher: PubcompPublisher->>Publisher: Delete(Msg)Subscriber->>Subscriber: Store(Msg)Subscriber->>Broker: PubrecBroker->>Subscriber: PubrelSubscriber->>Subscriber: Notify(Msg)Subscriber->>Broker: PubcompBroker->>Broker: Delete(Msg)Subscriber->>Subscriber: Delete(Msg)

總結(jié)

以上是生活随笔為你收集整理的mqtt 获取所有topic_MQTT协议解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。