搭建IM服務 so easy
現在很多網站、APP都通過IM服務來實現訊息推送及資料即時同步功能,即時通訊元件逐漸成為產品的標配。目前國內有很多成熟穩定的第三方即時通訊服務廠家,比如:融雲。使用這些專業的服務可以提高開發效率而且服務穩定有保障。
如果自己DIY或者需要在封閉的區域網內使用IM服務,該怎麼辦呢?下文就簡單介紹一下EasyPM曾經實踐過的自行搭建IM服務過程。
資料同步方式
實現資料同步,有”推”、”拉” 兩種思路,具體有以下幾種方式:
1. 使用HTTP輪循方式
- 說明:定時向HTTP服務端介面(Web Service API)獲取最新訊息,可結合ajax技術實現頁面無重新整理效果,這是主動拉取訊息的機制。
- 優點:實現簡單、可控性強、部署成本低
- 缺點:實時性差,增加服務端負載
2. 使用XMPP協議
- 說明:XMPP是基於可擴充套件標記語言(XML)的協議,它用於即時訊息(IM)以及線上現場探測。它促進在伺服器之間的準即時操作,其前身是Jabber,是一個開源形式組織產生的網路即時通訊協議。XMPP目前被IETF國際標準組織完成了標準化工作。
- 優點:協議成熟、強大、可擴充套件性強、目前主要應用於眾多IM系統
- 缺點:協議比較複雜、冗餘(基於XML)、費流量
3. 使用MQTT協議
- 說明:MQTT(Message Queuing Telemetry Transport,訊息佇列遙測傳輸)是IBM開發的一個即時通訊協議,該協議支援所有平臺,是輕量級的、基於代理的“釋出/訂閱”模式的訊息傳輸協議
- 優點:MQTT協議簡潔、可擴充套件性強、流量開銷很小、網路傳輸時間短
- 缺點:還不夠成熟、實現較複雜
EasyPM作為一個團隊協作應用,訊息/資料推送功能是不可或缺的。因為MQTT比較輕量且網路開銷小等特點,我們選擇了支援MQTT協議的Apollo。
Apollo是什麼?
Apollo是apache旗下的基金專案,它是以Apache ActiveMQ5.x為基礎,採用全新的執行緒和訊息排程架構重新實現的訊息中介軟體,針對多核處理器進行了優化處理,它的速度更快、更可靠、更易於維護。apollo與ActiveQQ一樣支援多協議:STOMP、AMQP、MQTT、Openwire、 SSL、WebSockets,本文只介紹MQTT協議的使用。
下載Apollo
如果操作是系統是Windows Vista或更高版本,則需要安裝Microsoft Visual C++ 2010 Redistributable:
64位JVM
32位JVM
建立Apollo例項及服務
- 建立例項
進入E:\apache-apollo-1.7
之下的bin目錄,開啟cmd視窗,執行命令:apollo create D:\apollo_broker
,命令執行成功後,在D盤下會有apollo_broker
目錄,這便是apollo的服務例項,apollo之旅便從這裡開始。
在D:\apollo_broker
下有個bin目錄,其中有兩個檔案:
apollo-broker.cmd是通過cmd命令啟動apollo服務的
apollo-broker-service.exe,是用於建立window服務的 - 命令列啟動服務
在D:\apollo_broker\bin
apollo-broker run
命令來啟動apollo服務,
啟動成功可以在瀏覽器中檢視執行情況,訪問地址為 http://127.0.0.1:61680 , 預設使用者名稱/密碼:admin/password
- 建立windows服務
找到cmd.exe
檔案,點選滑鼠右鍵,以管理員身份執行,輸入建立windows服務命令,如下圖:
建立成功後,在windows服務中會有一個apollo_broker
服務,設定隨系統自動啟動
MQTT協議的應用
MQTT協議有眾多客戶端實現,相關客戶端請參考apollo官方文件
本文采用eclipse的paho客戶端實現
web端接收訊息介紹
將 javascript客戶端專案下載下來,並在其專案根目錄下執行mvn命令,進行編譯,生成target目錄,其下生成mqttws31.js、mqttws31-min.js兩個js檔案,將其拷貝到自己專案相關目錄下,並在頁面中引用,即可實現javascript客戶端的訊息訂閱和釋出,demo程式碼如下:
var client = new Paho.MQTT.Client(location.hostname, 61623,"/", "clientId");
/* 61623是ws連線的預設埠,可以在apollo中介軟體中進行配置
(關於apollo的配置請參考:
http://activemq.apache.org/apollo/documentation/user-manual.html
) */
// set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
// connect the client
client.connect({userName:'admin',password:'password',onSuccess:onConnect});
// called when the client connects
function onConnect() { // 連線成功後的處理
// Once a connection has been made, make a subscription and send a message.
console.log("onConnect");
client.subscribe("/topic/event"); // 訂閱訊息的主題
var message = new Paho.MQTT.Message("Hello,this is a test");
message.destinationName = "/topic/event";
client.send(message); // 傳送訊息
}
// called when the client loses its connection
function onConnectionLost(responseObject) { // 連線丟失後的處理
if (responseObject.errorCode !== 0) {
console.log("onConnectionLost:"+responseObject.errorMessage);
}
}
// called when a message arrives
function onMessageArrived(message) { // 訊息接收成功後的處理
console.log("onMessageArrived:"+message.payloadString);
}
服務端訊息傳送介紹
paho java客戶端目前只支援J2SE和安卓,提供原始碼下載和maven庫。
我們採用maven庫,其地址如下:
Official Releases
Nightly Snapshots
maven dependency配置:
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.0.1</version>
</dependency>
java實現程式碼:
String topic = "MQTT Examples";
String content = "Message from MqttPublishSample";
int qos = 2;
String broker = "tcp://127.0.0.1:61613";
String clientId = "JavaSample";
MemoryPersistence persistence = new MemoryPersistence();
try {
MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
System.out.println("Connecting to broker: "+broker);
sampleClient.connect(connOpts);
System.out.println("Connected");
System.out.println("Publishing message: "+content);
MqttMessage message = new MqttMessage(content.getBytes());
message.setQos(qos);
sampleClient.publish(topic, message);
System.out.println("Message published");
sampleClient.disconnect();
System.out.println("Disconnected");
System.exit(0);
} catch(MqttException me) {
System.out.println("reason "+me.getReasonCode());
System.out.println("msg "+me.getMessage());
System.out.println("loc "+me.getLocalizedMessage());
System.out.println("cause "+me.getCause());
System.out.println("excep "+me);
me.printStackTrace();
}
小結
至此,MQTT協議已部署完畢,java端可以釋出訊息,而javascript端則可以訂閱並接收到java端釋出的資訊。在搭建的過程中,可以參考以下資源:
1. MQTT
2. ActiveMQ5
3. Apollo官方文件
4. eclipse paho