【MQTT系列】Eclipse Mosquitto實戰
雖然我強烈推薦使用EMQ,但是Mosquitto也是非常有必要了解的。
Mosquitto的英文意思是 蚊子 。
由於Mosquitto的安裝比較簡單,本文不會具體描述,本文測試介紹Mosquitto的概念、客戶端以及如何使用Java程式碼跑通Mosquitto的功能。
在文章的最後,也會說明Mosquitto存在的一些問題以及我不選擇它的一些理由。
Mosquitto介紹
Eclipse Mosquitto是一個開源(EPL / EDL許可)訊息代理,它實現了MQTT協議版本3.1和3.1.1。Mosquitto重量輕,適用於從低功耗單板計算機到完整伺服器的所有裝置。
MQTT協議提供了一種使用釋出/訂閱模型執行訊息傳遞的輕量級方法。這使其適用於物聯網訊息傳遞,例如低功率感測器或移動裝置,如電話,嵌入式計算機或微控制器。
Mosquitto專案還提供了用於實現MQTT客戶端的C庫,以及非常流行的mosquitto_pub和mosquitto_sub命令列MQTT客戶端。
Mosquitto是Eclipse Foundation的一部分,是一個iot.eclipse.org專案。
官網:
正常來說,如果是Java專案我們可以引入如下依賴
<dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse.paho.client.mqttv3</artifactId> <version>1.2.0</version> </dependency>
Mosquitto Java 客戶端實現
Mosquitto 訊息傳送主要分為三個類:
PubMsg 客服端釋出訊息
PushCallback 訊息回撥
SubMsg 訂閱訊息
下面我們一起來看這個示例程式:
PubMsg
package com.example.mqtt.publish; import org.eclipse.paho.client.mqttv3.*; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; /** * 傳送訊息到MQTT */ public class PubMsg { private static int qos = 2; //只有一次 private static String broker = "tcp://XXXXXXXXX:1883"; private static String userName = "admin"; private static String passWord = "admin"; private static MqttClient connect(String clientId, String userName, String password) throws MqttException { MemoryPersistence persistence = new MemoryPersistence(); MqttConnectOptions connOpts = new MqttConnectOptions(); connOpts.setCleanSession(true); connOpts.setUserName(userName); connOpts.setPassword(password.toCharArray()); connOpts.setConnectionTimeout(10);// 設定超時時間 connOpts.setKeepAliveInterval(20); // 設定會話心跳時間 // String[] uris = {"tcp://10.100.124.206:1883","tcp://10.100.124.207:1883"}; // connOpts.setServerURIs(uris); //起到負載均衡和高可用的作用 // broker,clientid即連線MQTT的客戶端ID,一般以唯一識別符號表示,MemoryPersistence設定clientid的儲存形式,預設為以記憶體儲存 MqttClient mqttClient = new MqttClient(broker, clientId, persistence); /* // MQTT的連線設定 MqttConnectOptions options = new MqttConnectOptions(); // 設定是否清空session,這裡如果設定為false表示伺服器會保留客戶端的連線記錄,這裡設定為true表示每次連線到伺服器都以新的身份連線 options.setCleanSession(true); // 設定連線的使用者名稱 options.setUserName(userName); // 設定連線的密碼 options.setPassword(passWord.toCharArray()); // 設定超時時間 單位為秒 options.setConnectionTimeout(10); // 設定會話心跳時間 單位為秒 伺服器會每隔1.5*20秒的時間向客戶端傳送個訊息判斷客戶端是否線上,但這個方法並沒有重連的機制 options.setKeepAliveInterval(20); MqttTopic topic = mqttClient.getTopic("test-topic"); // setWill方法,如果專案中需要知道客戶端是否掉線可以呼叫該方法。設定最終埠的通知訊息 options.setWill(topic, "close".getBytes(), 2, true);*/ mqttClient.setCallback(new PushCallback("test")); mqttClient.connect(connOpts); return mqttClient; } private static void pub(MqttClient sampleClient, String msg, String topic) throws MqttPersistenceException, MqttException { MqttMessage message = new MqttMessage("Hello Charles!".getBytes()); message.setQos(qos); message.setRetained(false); sampleClient.publish(topic, message); } private static void publish(String str, String clientId, String topic) throws MqttException { MqttClient mqttClient = connect(clientId, userName, passWord); if (mqttClient != null) { pub(mqttClient, str, topic); System.out.println("pub-->" + str); } if (mqttClient != null) { mqttClient.disconnect(); } } public static void main(String[] args) throws MqttException { publish("message content", "client-id-0", "test-topic"); } }
PushCallback
package com.example.mqtt.publish; import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; import org.eclipse.paho.client.mqttv3.MqttCallback; import org.eclipse.paho.client.mqttv3.MqttMessage; /** * 釋出訊息的回撥類 * * 必須實現MqttCallback的介面並實現對應的相關介面方法CallBack 類將實現 MqttCallBack。 * 每個客戶機標識都需要一個回撥例項。在此示例中,建構函式傳遞客戶機標識以另存為例項資料。 在回撥中,將它用來標識已經啟動了該回撥的哪個例項。 * 必須在回撥類中實現三個方法: * * public void messageArrived(MqttTopic topic, MqttMessage message)接收已經預訂的釋出。 * * public void connectionLost(Throwable cause)在斷開連線時呼叫。 * * public void deliveryComplete(MqttDeliveryToken token)) 接收到已經發布的 QoS 1 或 QoS 2 * 訊息的傳遞令牌時呼叫。 由 MqttClient.connect 啟用此回撥。 * */ class PushCallback implements MqttCallback { private String threadId; public PushCallback(String threadId) { this.threadId = threadId; } public void connectionLost(Throwable cause) { // 連線丟失後,一般在這裡面進行重連 System.out.println("連線斷開,可以做重連"); } public void deliveryComplete(IMqttDeliveryToken token) { System.out.println("deliveryComplete---------" + token.isComplete()); } public void messageArrived(String topic, MqttMessage message) throws Exception { String msg = new String(message.getPayload()); System.out.println("-------messageArrived-------"+threadId + " " + msg); } }
SubMsg
package com.example.mqtt.subscribe; import org.eclipse.paho.client.mqttv3.IMqttMessageListener; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; public class SubMsg { private static int qos = 2; private static String broker = "tcp://XXXXXXX:1883"; private static MqttClient connect(String clientId) throws MqttException{ MemoryPersistence persistence = new MemoryPersistence(); MqttConnectOptions connOpts = new MqttConnectOptions(); connOpts.setCleanSession(false); connOpts.setConnectionTimeout(10); connOpts.setKeepAliveInterval(20); connOpts.setUserName("admin"); connOpts.setPassword("admin".toCharArray()); MqttClient mqttClient = new MqttClient(broker, clientId, persistence); mqttClient.connect(connOpts); return mqttClient; } public static void sub(MqttClient mqttClient,String topic) throws MqttException{ int[] Qos = {qos}; String[] topics = {topic}; mqttClient.subscribe(topics, Qos); } private static void runsub(String clientId, String topic) throws MqttException{ MqttClient mqttClient = connect(clientId); if(mqttClient != null){ sub(mqttClient,topic); } mqttClient.subscribe(topic,2, new IMqttMessageListener() { @Override public void messageArrived(String topic, MqttMessage message) throws Exception { System.out.println("接收訊息主題 : " + topic); System.out.println("接收訊息Qos : " + message.getQos()); System.out.println("接收訊息內容 : " + new String(message.getPayload())); } }); } public static void main(String[] args) throws MqttException{ runsub("testSub", "test-topic"); } }
執行結果
啟動SubMsg訂閱訊息,再啟動PubMsg傳送訊息
1)PubMsg顯示傳送成功:
2)SubMsg也會收到資訊:
為什麼線上環境不考慮使用Mosquitto?
線上環境需要使用叢集模式,雖然官方可以使用bridge功能,連線多個mqtt broker,但是還是存在一些問題。原因主要有如下幾個:
Mosquitto半年多沒維護了,版本也不是最新的
如果增加bridge節點,需要修改多個節點的配置,並且重啟,維護成本高
叢集模式如果主節點down機,所有從伺服器會變成孤立的節點
down機節點重新啟動以後,容易造成負載不均衡
我們有更好的方案EMQ
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31555484/viewspace-2375531/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 橋接 Mosquitto MQTT 訊息至 EMQX橋接UIMQQT
- MQTT 實戰MQQT
- EMQX vs Mosquitto | 2023 MQTT Broker 對比MQUIQT
- Mosquitto vs NanoMQ | 2023 MQTT Broker 對比UINaNMQQT
- MQTT系列實踐二 在EGG中使用mqttMQQT
- mosquittoUI
- MQTT系列實踐一 EMQTT安裝與測試MQQT
- Canal PHP[實戰系列]PHP
- RocketMQ實戰系列從理論到實戰MQ
- mosquitto_pub和mosquitto_sub 命令引數說明UI
- mosquitto 引數配置UI
- Guzzle7[實戰系列]
- Maven實戰系列文章Maven
- shiro實戰系列(二)之入門實戰續
- ElasticSearch實戰系列六: Logstash快速入門和實戰Elasticsearch
- MQTT協議實踐MQQT協議
- ElasticSearch實戰系列七: Logstash實戰使用-圖文講解Elasticsearch
- 域滲透之ATT&CK實戰系列——紅隊實戰(一)
- 專案實戰-物聯網平臺搭建-mqtt伺服器搭建(一)MQQT伺服器
- mosquitto命令引數說明UI
- webpack 快速入門 系列 —— 實戰一Web
- AspNetCore - MVC實戰系列(一)NetCoreMVC
- [Jira] Jira4系列、Jira6系列破解實戰
- 實驗一--Easy IoT實現mqtt實驗MQQT
- Linux 安裝Mosquitto服務LinuxUI
- Flutter 實戰系列:個性化 ListView physicsFlutterView
- Selenium實戰教程系列(二)—元素定位
- Selenium實戰教程系列(二)---元素定位
- rust實戰系列-base64編碼Rust
- 深入Weex系列(二)之列表頁實戰
- 小丸子學Docker系列之——實戰DockerfileDocker
- MongoDB實戰系列之六:mongodb的高可用叢集設計實戰薦MongoDB
- 如何實現歐姆龍CJ/CS/CP系列PLC接入MQTT裝置管理雲平臺?MQQT
- 【asp.net core 系列】10 實戰之ActionFilterASP.NETFilter
- 小程式從入門到實戰系列(一)
- go-zero微服務實戰系列(十一、大結局)Go微服務
- Elasticsearch學習系列三(搜尋案例實戰)Elasticsearch
- Spring Boot Serverless 實戰系列 | 效能調優Spring BootServer