MQTT使用踩坑

zs40122發表於2019-01-24

現象:在最近開發的IoT專案中使用MQ同邊緣服務模組進行通訊。當硬體裝置離網,邊緣服務會取消訂閱相關Topic。裝置上電上網時,邊緣服務會訂閱相關Topic,然後上報裝置資料到我負責開發的服務來進行更新處理同時也會發起同步資料的操作。根據規則,更新操作時我這邊是不會返送一個MQ訊息的,並且控制檯的日誌也未見由更新操作yinf日誌,但是邊緣服務硬是有收到一條發自我這邊的MQ訊息!

原因:

@Override
    public Boolean publish(String topic, String content) {
        log.info("MQ---public--- 入參:topic:{};content:{}", topic, content);
        MqttMessage message = new MqttMessage(content.getBytes());
        message.setQos(mqttConfiguration.getQos());
        /**
         * Retained為true時MQ會保留最後一條傳送的資料,當斷開再次訂閱即會接收到這最後一次的資料
         */
        message.setRetained(false);
        MqttClient mqttClient = publishRunner.getMqttPubClient();
        try {
            // 判定是否需要重新連線
            if (mqttClient==null || !mqttClient.isConnected()) {
                mqttClient = publishConn.getConn();
                publishRunner.setMqttPubClient(mqttClient);
                log.info("---mq重新連線---:{}",mqttClient.getClientId());
            }
            mqttClient.publish(topic, message);
            log.info("emq已發topic: {} - message: {}", topic, message);
        } catch (Exception e) {
            log.info("MQ---public--- 釋出失敗!::Error::{}", JSON.toJSONString(e));
            return false;
        }
        log.info("MQ---public--- 釋出成功!:topic:{};content:{}", topic, content);
        return true;
    }
message.setRetained(false);

這裡應該設定為false!當為true時,MQ會保留最後傳送的一條訊息,當Topic被再次訂閱時會收到該條訊息。

這讓我想到之前我負責的服務每次重啟時都會接收到MQ訊息,但對應訊息生產者並未發出訊息...

Demo專案:https://github.com/MrZhangsGit/SpringCloudStudy