項目背景:
? ? ? ?在 Spring Boot +?MQTT?5.0 環境中,RTU設備向SpringBoot平臺發送心跳數據、業務監控數據。同時SpringBoot平臺可以向RTU設備下發指令,RTU在執行完指令之后向平臺發送響應數據。
? ? ? ? 問題一、SpingBoot平臺發送指令給RTU設備,RTU設備能夠收到指令也能回復信息到相應的主題。SpringBoot平臺也訂閱該主題,但是沒有收到信息。
? ? ? ? 在遇到這個問題的時候,我發現控制臺的打印出了一個ERROR日志:
2025-03-06 11:11:31.652 [MQTT Rec: TerminalB] ERROR o.s.i.m.i.MqttPahoMessageDrivenChannelAdapter:362 - Lost connection: 已斷開連接; retrying...
排查思路:
1.首先需要明確哪些因素會導致出現斷開連接。因為收不到消息同時伴隨著ERROR日志的打印。
-
?檢查網絡連接
?????????確保你的設備與MQTT服務器之間的網絡連接是穩定的。你可以嘗試ping服務器地址或使用網絡工具檢查連接質量。
-
?檢查MQTT服務器狀態
????????確認MQTT服務器正在運行且沒有遇到任何問題。如果可能,嘗試連接到服務器的其他客戶端(例如另一個設備或應用程序)以驗證服務器是否可用。
-
?檢查MQTT客戶端配置????????????
-
? ? 主機名和端口:確保客戶端配置中的MQTT服務器地址和端口號是正確的。
-
? ? 客戶端ID:每個客戶端都應該有一個唯一的ID。確保沒有兩個客戶端使用相同的ID連接至同一服務器。
-
? ? 用戶名和密碼:如果服務器啟用了認證,確保提供了正確的用戶名和密碼。
-
? ? 清潔會話:根據你的需求設置
cleanSession
。如果是true,它將刪除之前的會話信息;如果是false,它將保留會話信息。 -
? 檢查防火墻和安全組設置
????????確保沒有防火墻或安全組規則阻止客戶端與MQTT服務器之間通信。這包括入站和出站規則。
2、SpringBoot平臺訂閱了很多主題的消息,比如心跳主題,業務監控主題等,之前是不會出現信息訂閱不到。說明主機名和端口、用戶名密碼,是正確的。
3、現在還剩下三項沒有排除,客戶端ID、清潔會話、防火墻。因為心跳是正常的,所以說清潔會話和防火墻是沒問題的,如果這兩個有問題那心跳主題的信息我們平臺也是收不到的。
4、目前只剩下客戶端ID這個因素。現在已經大致明確了是因為這個因素導致,接下來我們需要分析一下為什么出現這個問題,之前是正常的。通過回憶實際操作,我發現SpingBoot平臺訂閱不到消息之前,我通過SpringBoot平臺向某一臺RTU設備發送了一個修改頻率的指令。然后我又分析日志信息,發現當我發送消息之后,控制臺出現了斷開連接的錯誤。好,現在我把所有的操作和具體的報錯信息聯系在一起,問題就比較清晰了。我發送了一個指令,控制臺報錯:斷開連接,然后RTU執行指令,然后RTU向響應主題發送消息,我們SpingBoot平臺收不到了。
? ? ? ? 再把上述的問題精簡一下對于SprintBoot平臺其實就是兩個操作,一個是平臺利用MQTT發送消息,另一個就是平臺利用MQTT訂閱消息。當我發送完消息,平臺訂閱不到消息,同時出現斷開連接。這個時候我就明確了錯誤所在,發布是一個客戶端行為,訂閱也是一個客戶端行為,但是我們在代碼里面把訂閱ID和發送ID設置成了相同的,如下:
subClientId: adminpubClientId: admin
? ? ? ? 也就是平臺發送指令的時候把訂閱的連接頂掉了,這個時候出現了訂閱斷開連接的錯誤日志。然后RTU發送響應消息到訂閱主題,但是這個時候平臺的訂閱已經斷開鏈接,所以說平臺一直收不到響應消息。以上就是我分析這個問題的具體思路,在此僅作個人記錄,如有分析錯誤的地方,歡迎大家留言指導。
問題二、SpingBoot平臺在啟動之后,一直在重復打印一條消息,而且RTU設備并沒有發送任何消息到MQTT的服務器,通過觀察該消息是間隔固定的時間重復打印。
? ? ? ??排查思路:
1、我先排查這一條消息的出處到底在哪里來的。通過對比發現,這一條是昨天RTU的消息,并不是今天的,所以說很奇怪。
2、MQTT通訊中我的平臺也是一個客戶端,客戶端本身不存儲消息,只有可能是服務器端存儲。
3、前邊幾篇文章分析的有消息重復接受的原因,主要是消息質量為1的時候,MQTT協議本身重發導致。還有就是tcp的重發,但是在這里不存在tcp重復的因素。那只能是消息質量為1的時候,協議本身導致。
4、現在分析出主要是消息質量為1的時候導致,那就說明broker給平臺發送消息的時候可能存在兩種情況,第一就是broker收到多次重復消息,導致broker也給平臺發送多次消息。第二、就是平臺收到broker消息,但是平臺沒有給broker發送回復消息。
5、如果是第一種情況,那我平臺正常啟動,就能消費訂閱的信息,就不會出現我現在這種不斷重復打印的情況,所以說第一種情況排除。
6、那現在肯定是第二種情況,平臺沒有給broker發送響應消息。現在開始回顧代碼,為什么沒有發送響應消息。仔細觀察代碼發現,我訂閱的時候使用通配符訂閱了所有消息,恰好沒有對RTU執行代碼之后發送消息的主題進行代碼處理,導致broker一直收不到我的平臺反饋,所以說broker一直不斷地給平臺發送信息。
7、綜上所述這就是我重復消息不停輸出的原因。