客戶端可以在訂閱時指定一個訂閱標識符,服務端將在訂閱成功創建或修改時建立並存儲該訂閱與訂閱標識符的映射關係。當有匹配該訂閱的 PUBLISH 報文要轉發給此客戶端時,服務端會將與該訂閱關聯的訂閱標識符隨 PUBLISH 報文一併返回給客戶端。
因此,客戶端可以建立訂閱標識符與消息處理程序的映射,以在收到 PUBLISH 報文時直接通過訂閱標識符將消息定向至對應的消息處理程序,這會遠遠快於通過主題匹配來查找消息處理程序的速度。
由於 SUBSCRIBE 報文支持包含多個訂閱,因此可能出現多個訂閱關聯到同一個訂閱標識符的情況。即便是分開訂閱,也可能出現這種情況,但這是被允許的,只是用戶應當意識到這樣使用可能引起的後果。根據客戶端的實際訂閱情況,最終客戶端收到的 PUBLISH 報文中可能包含多個訂閱標識符,這些標識符可能完全不同,也可能有些是相同的,以下是幾種常見的情況:
客戶端訂閱主題 a 並指定訂閱標識符為 1,訂閱主題 b 並指定訂閱標識符為 2。由於使用了不同的訂閱標識符,主題為 a 和 b 的消息能夠被定向至不同的消息處理程序。
客戶端訂閱主題 a 並指定訂閱標識符為 1,訂閱主題 b 並指定訂閱標識符為 1。由於使用了相同的訂閱標識符,主題為 a 和 b 的消息都將被定向至同一個消息處理程序。
客戶端訂閱主題 a/+ 並指定訂閱標識符為 1,訂閱主題 a/b 並指定訂閱標識符為 1。主題為 a/b 的 PUBLISH 報文將會攜帶兩個相同的訂閱標識符,對應的消息處理程序將被觸發兩次。
客戶端訂閱主題 a/+ 並指定訂閱標識符為 1,訂閱主題 a/b 並指定訂閱標識符為 2。主題為 a/b 的 PUBLISH 報文將會攜帶兩個不同的訂閱標識符,一個消息將觸發兩個不同的消息處理程序。
這種 PUBLISH 報文中攜帶多個訂閱標識符的情況,在消息速率低的時候通常不成問題,但在消息速率高時可能會引發一些性能問題,因此我們建議您儘量確保這種情況的出現都是您有意為之。
在 MQTT v5 中,你可以使用更多的訂閱選項來改變服務端的行為。
QoS參見 MQTT 消息服務質量等級 (https://www.emqx.io/cn/blog/introduction-to-mqtt-qos)。
No Local在 MQTT v3.1.1 中,如果你訂閱了自己發布消息的主題,那麼你將收到自己發布的所有消息。
而在 MQTT v5 中,如果你在訂閱時將此選項設置為 1,那麼服務端將不會向你轉發你自己發布的消息。
Retain As Publish這一選項用來指定服務端向客戶端轉發消息時是否要保留其中的 RETAIN 標識,注意這一選項不會影響保留消息中的 RETAIN 標識。因此當 Retain As Publish 選項被設置為 0 時,客戶端直接依靠消息中的 RETAIN 標識來區分這是一個正常的轉發消息還是一個保留消息,而不是去判斷消息是否是自己訂閱後收到的第一個消息(轉發消息甚至可能會先於保留消息被發送,視不同 Broker 的具體實現而定)。
Retain Handling這一選項用來指定訂閱建立時服務端是否向客戶端發送保留消息:
Retain Handling 等於 0,只要客戶端訂閱成功,服務端就發送保留消息。
Retain Handling 等於 1,客戶端訂閱成功且該訂閱此前不存在,服務端才發送保留消息。畢竟有些時候客戶端重新發起訂閱可能只是為了改變一下 QoS,並不意味著它想再次接收保留消息。
Retain Handling 等於 2,即便客戶訂閱成功,服務端也不會發送保留消息。