2019-04-19
看了4.3服務(wù)質(zhì)量級別(Quality of Service levels)的介紹,覺得QoS1和QoS2的協(xié)議應(yīng)該存在一些漏洞(或者說是不完美)取逾。
- QoS1的不完美
QoS1是至少投遞成功一次( At least once delivery),確保消息一定發(fā)送給接收者友扰。 需要兩次握手农猬。
QoS1消息發(fā)送的過程是這樣的:
1.消息發(fā)送者發(fā)送PUBLISH包(包含一個未使用的PackId),并等待接收者返回PUBREC包探遵;
2.接收者接收到PUBLISH包,處理這個包妓柜,并響應(yīng)一個PUBREC包給發(fā)送者箱季。此后,對于后續(xù)的具有相同的PackId的PUBLISH包都要作為新的消息處理棍掐,并且不用管該包的DUP標志藏雏。
3.發(fā)送者收到同一個PackId的PUBREC包,結(jié)束掉這個PackId的消息作煌。之后可以重復(fù)使用該PackId作為新消息包的識別值掘殴。
QoS1消息的不完美之處的分析:
鑒于上述的2、3點粟誓,發(fā)送者由于某些原因(比如長時間沒有收到接收者返回的PUBREC)對同一個PackId的包重復(fù)發(fā)送了多次奏寨,接收者接收到了一次PUBLISH進行處理后又接收到了發(fā)送者重復(fù)發(fā)送的PUBLISH,由于第2點的規(guī)定鹰服,對其進行了第二次的處理病瞳,這個問題是QoS1級別本身就不打算解決的揽咕,所以要避免這個問題需要使用QoS2消息級別。但我要說的不完美不是這一點套菜,而是可能出現(xiàn)的同一個PackId被重用之后的新消息沒有被接收者真正的接收到亲善。試想,如果第一次的PUBLISH消息被接收者重復(fù)處理了并返回了多個PUBREC給發(fā)送者逗柴,發(fā)送者接收到了其中一個PUBREC蛹头,結(jié)束了第一次的PUBLISH消息,又重用這個PackId發(fā)送新的PUBLISH消息戏溺,但同時原來的PUBLISH的多個PUBREC中的一個返回到了發(fā)送者渣蜗,此時新的PUBLISH還沒被接收者接收到,但發(fā)送者誤認為現(xiàn)在接收到PUBREC是接收者對新的PUBLISH的響應(yīng)旷祸,就將新的那個PUBLISH消息結(jié)束掉了袍睡。這種情況下,如果接收者沒有接到新的PUBLISH包就永遠不會可能再接收到了肋僧,因為發(fā)送者誤以為接收者已接收到,不會重復(fù)發(fā)送這個新的PUBLISH消息了控淡。 - QoS2的不完美
QoS2是只正確的投遞一次( Exactly once delivery)嫌吠,保證消息有且只有一次成功的投遞。需要四次握手掺炭,兩次響應(yīng)辫诅。
QoS2的傳遞過程:
- 消息發(fā)送者發(fā)送PUBLISH包(包含一個未使用的PackId),并等待接收者返回PUBREC包涧狮;在未接到PUBREL之前炕矮,對于后續(xù)接收的PUBLISH都必須要響應(yīng)一個PUBREC,但此時不能造成多個消息傳遞給發(fā)送者者冤。
- 接收者接收到PUBLISH包肤视,處理這個包,響應(yīng)一個PUBREC包涉枫。并等待PUBREL包邢滑;
- 發(fā)送者收到同一個PackId的PUBREC包,響應(yīng)一個PUBREL包愿汰,并等待PUBCOMP困后。此時,發(fā)送者不能發(fā)送PUBLISH衬廷。
- 接收者接收到PUBREL包摇予,響應(yīng)一個PUBCOMP吗跋。之后接收到的相同的PackId的PUBLISH需要作為新的消息處理侧戴。
5.接收者接收到PUBCOMP后,結(jié)束消息。之后可以重復(fù)使用PackId.
QoS2消息的不完美之處的分析:
對于同一消息發(fā)送者多次發(fā)送了救鲤,由于某些因素(比如網(wǎng)絡(luò)延遲)久窟,其中一次到達接收者的時間晚于其他次發(fā)送的,前面到達的早已被接收者處理過了(早和發(fā)送者完成后續(xù)的握手動作了)本缠,因此這個消息會被接收者重復(fù)處理斥扛。
QoS1和QoS的不完美的解決想法
對于QoS1,只要發(fā)送者不短時間內(nèi)重用相同的PackId就可以避免了丹锹。對于QoS2稀颁,需要發(fā)送者不短時間內(nèi)重用相同的PackId,同時需要接收者在短時間接收到一個剛處理完的PackId消息棄置不理(發(fā)送者會重復(fù)發(fā)送消息楣黍,不會造成新信息接收不到的)匾灶。