雲Message QueueTT 版提供同步查詢和非同步上下線事件通知兩種方式,來擷取MQTT用戶端線上狀態。本文介紹這兩種方式的基本原理、應用情境、具體差異以及實現方式。
基本原理
雲Message QueueTT 版服務端(下文簡稱為MQTT服務端)提供以下方式擷取用戶端線上狀態:
- 同步查詢
該方式相對簡單,即通過開放的存取點地址調用HTTP/HTTPS方式的OpenAPI查詢某個特定用戶端的當前即時狀態,適用於對單個或多個用戶端的狀態判斷。
- 非同步上下線事件通知
該方式使用訊息通知,在用戶端上線和下線事件觸發時,MQTT服務端支援將上下線訊息直接推送到部署在阿里雲伺服器上的雲端應用。
該方式屬於非同步感知用戶端的狀態,且感知到的是上下線事件,而非線上狀態,雲端應用需要根據事件發生的時間序列分析出用戶端的狀態。
應用情境
兩種擷取MQTT用戶端線上狀態的方式分別應用於以下情境:
- 同步查詢
- 主商務程序中需要根據用戶端是否線上來決定後續運行邏輯。
- 營運過程需要判斷特定用戶端當前是否線上。
- 非同步上下線事件通知
- 服務端需要在用戶端上線或者下線時觸發一些預定義的動作。
- 服務端需要對用戶端的上下線資料進行統計分析,並根據用戶端的線上狀態推送訊息。
同步查詢與非同步事件通知的差異
兩種查詢方式的區別如下:
- 同步查詢是查詢當前用戶端的即時狀態,理論上比非同步通知的方式更精確。
- 非同步上下線通知因為採用訊息解耦,狀態判斷更加複雜,且誤判可能性更大,但該方法可以基於事件分析多個用戶端的運行狀態軌跡。非同步通知雖然存在一定複雜度和誤判,但更加適合大規模的用戶端的狀態統計。
實現方式
- 同步查詢
同步查詢方式可以通過調用以下API介面擷取用戶端狀態:
- 非同步上下線事件通知
非同步上下線事件通知方式下,雲端服務可通過調用雲Message QueueTT 版提供的雲端SDK擷取用戶端上下線訊息。SDK下載,請參見版本說明。
擷取用戶端上下線事件的範例程式碼如下:說明在使用範例程式碼前,需要配置環境變數,通過環境變數讀取存取憑證。關於配置環境變數的方法,請參見配置訪問憑證。
雲Message QueueTT 版的AccessKey ID和AccessKey Secret的環境變數名稱分別為MQTT_AK_ENV和MQTT_SK_ENV。
package com.aliyun.openservices.lmq.example; import com.alibaba.fastjson.JSONObject; import com.alibaba.mqtt.server.ServerConsumer; import com.alibaba.mqtt.server.callback.StatusListener; import com.alibaba.mqtt.server.config.ChannelConfig; import com.alibaba.mqtt.server.config.ConsumerConfig; import com.alibaba.mqtt.server.model.StatusNotice; public class MQTTClientStatusNoticeProcessDemo { public static void main(String[] args) throws Exception { /** * 您建立的雲Message QueueTT 版的執行個體存取點。 * 擷取雲端SDK的存取點,請聯絡支援人員,DingTalk群號:35228338。。 * 存取點地址必須填寫分配的網域名稱,不得使用IP地址直接連接,否則可能會導致服務端異常。 */ String domain = "domain"; /** * 使用的協議和連接埠必須匹配,該參數值固定為5672。 */ int port = 5672; /** * 您建立的雲Message QueueTT 版的執行個體ID。 */ String instanceId = "instanceId"; /** * AccessKey ID,阿里雲身分識別驗證,在阿里雲RAM控制台建立。 * 阿里雲帳號AccessKey擁有所有API的存取權限,建議您使用RAM使用者進行API訪問或日常營運。 * 強烈建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。 * 本樣本以將AccessKey 和 AccessKeySecret 儲存在環境變數為例說明。 */ String accessKey = System.getenv("MQTT_AK_ENV"); /** * AccessKey Secret,阿里雲身分識別驗證,在阿里雲RAM控制台建立。僅在簽名鑒權模式下需要設定。 */ String secretKey = System.getenv("MQTT_SK_ENV"); /** * 您在雲Message QueueTT 版控制台建立的Group的ID。 * */ String mqttGroupId = "mqttGroupId"; ChannelConfig channelConfig = new ChannelConfig(); channelConfig.setDomain(domain); channelConfig.setPort(port); channelConfig.setInstanceId(instanceId); channelConfig.setAccessKey(accessKey); channelConfig.setSecretKey(secretKey); ServerConsumer serverConsumer = new ServerConsumer(channelConfig, new ConsumerConfig()); serverConsumer.start(); serverConsumer.subscribeStatus(mqttGroupId, new StatusListener() { @Override public void process(StatusNotice statusNotice) { System.out.println(JSONObject.toJSONString(statusNotice)); } }); } }