XMPP
XMPP(可擴展消息處理現場協議)是基於可擴展標記語言(XML)的協議,它用於即時消息(IM)以及在線現場探測。是一種數據傳輸協議。
XMPP的前身是Jabber,一個開源形式組織產生的網絡即時通信協議。
XMPP 地址格式
一個XMPP節點的唯一標示符jabber identifier(JID),即實體地址,用來表示一個Jabber用戶,但是也可以表示其他內容,例如一個聊天室.
一個有效的JID包括一系列元素:
- (1)域名(domain identifier);
- (2)節點(node identifier);
- (3)源(resource identifier).
它的格式是 node@domain/resource,node@domain,類似電子郵件的地址格式.
- domain用來表示接點不同的設備或位置,這個是可選的,例如a在Server1上注冊了一個用戶,用戶名為doom,那么a的JID就是 doom@serverl,在發送消息時,指明 doom@serverl 就可以了,
- resource可以不用指定,但a在登錄到這個Server時,fl的JID可能是 doom@serverl/exodus (如果a用Exodus軟件登錄),也可能是 doom@serverl/psi (如果a用psi軟件登錄).資源只用來識別屬於用戶的位置或設備等,一個用戶可以同時以多種資源與同一個XMPP服務器連接。
XMPP 協議的 XML 格式:
這里有三個頂級 XML 元素: Presence、Message、IQ,每個的含義如下:
<Presence> 用來表明用戶的狀態,
如:online、away、dnd(請勿打擾)等。當用戶離線或改變自己的狀態時,就會在stream的上下文中插入一個Presence元素,來表明自身的狀態.
<Message> 用於在兩個jabber用戶之間發送信息。
Jsm(jabber會話管理器)負責滿足所有的消息,不管目標用戶的狀態如何。如果用戶在線jsm立即提交;否則jsm就存儲。
To :標識消息的接收方。
from : 指發送方的名字或標示(id)o
Text: 此元素包含了要提交給目標用戶的信息。
< IQ > 一種請求/響應機制,
從一個節點從發送請求,另外一個節點接受請求,並進行響應.
例如,client在stream的上下文中插入一個元素,向Server請求得到自己的好友列表,Server返回一個,里面是請求的結果.
<iq > 主要的屬性是type。包括:
Get :獲取當前域值。
Set :設置或替換get查詢的值。
Result :說明成功的響應了先前的查詢。
Error: 查詢和響應中出現的錯誤。
XML流
XMPP本質上是一種XML流技術。
客戶端開始和XMPP服務器會話,會打開一個長時間的TCP連接,然后和服務器協商一個流。
一旦你和你的服務器建立了一個XML流,你和你的服務器可以通過流交換三個特殊的XML片段:<message/>,<presence/>,<iq/>.這些片段稱為XML節。而且一旦你已建立一個XML流,你可以通過流發送無數個節。
下圖是 C 客戶端 S 服務器端 XML流的精簡內容:
C: <stream:stream> C: <presence/> C: <iq type="get"> <query xmlns="jabber:iq:roster"/> </iq> S: <iq type="result"> <query xmlns="jabber:iq:roster"> <item jid="suke@skh.whu.edu.cn"xs/> <item jid="gmz@skh.whu.edu.cn"/> <item jid="beta@skh.whu.edu.cn"/> </query> </iq> C: <message from="suke@skh.whu.edu.cn" to="beta@skh.whu.edu.cn"> <body>Off with his head!</body> </message> S: <message from="lj@skh.whu.edu.cn" to="cyl@skh.whu.edu.cn "> <body>You are all pardoned.</body> </message> C: <presence type="unavailable"/> C: </stream:stream>
XMPP面臨的問題:
- XMPP是基於穩定長連接網絡環境所設計的,對於不夠穩定和帶寬小的移動網絡不是非常合適。
- 由於XMPP基於XML,所以流量大,流量問題對於移動網絡來說非常敏感,然后就是消息不可靠、CMWAP兼容、開源項目對協議實現不完善等問題,也是XMPP面臨的問題。
數據負載太重:隨着通常超過 70%的 XMPP 協議的服務器的數據流量的存在和近60%的被重復轉發,XMPP 協議目前擁有一個大型架空中存在的數據提供給多個收件人。新的議定書正在研究,以減輕這一問題。
沒有二進制數據:XMPP 協議的方式被編碼為一個單一的長的 XML 文件,因此無法提供修改二進制數據。因此, 文件傳輸協議一樣使用外部的 HTTP。如果不可避免,XMPP 協議還提供了帶編碼的文件傳輸的所有數據使用的 Base64。至於其他二進制數據加密會話(encrypted conversations)或圖形圖標(graphic icons)以嵌入式使用相同的方法。
XMPP 優化的一個方案是:
- XML通過精簡壓縮來實現流量可控。
- 消息的不可靠可以通過擴展XMPP來實現ACK
OpenFire
Openfire是XMPP領域最知名的開源項目,它簡單易用,是很多團隊的首選方案,這是國內使用最多的開源方案。Openfire雖然優點很多,但是缺點也不少,最致命的就是它的分布式擴展能力很弱,當用戶量很大的時候,水平擴展就成為它的瓶頸所在。
消息握手
經常會有人發現,Openfire的兩個客戶端,在網絡不穩定的情況下,會丟失消息。起初我也不知道到底發生了什么,直到后來,在測試中發現,當你用連接上通訊服務器后,直接拔了路由器,wifi異常斷開,客戶端與Server沒辦法握手告知TCP斷線的事情,所以你會在一段時間內,服務器認為你在線,而實際你離線。這種情況在地鐵、快速移動切換網絡基站的情況下也經常有復現。此時Openfire收到關於你的消息會直接推送給你,而你此時又因為沒有網絡收取不到,所以消息丟失。
解決辦法:消息進行握手,每條消息發給客戶端,都需要客戶端回復回執,否則一直保存在服務器。
心跳機制
因為上述問題,所以就要經常清理那些失效客戶端,保證客戶端和服務器狀態同步。
如每15s - 60s 客戶端定時發送一個小型的msg給服務器,服務器收到后回復一個callback。
如果服務器120s內沒有收取到任何消息,那么close Session。
雖然XMPP有很多弊端,但是它的生態目前是最完善的,如果從成本角度來考量,XMPP是前期投入最小產出最快的。但是如果是搭建一個SAAS平台或者千萬量級的IM,XMPP就不是最優的選擇了。
參考資料:
漫談IM通信架構
http://www.yangguo.info/2015/08/17/%E6%BC%AB%E8%B0%88%E9%80%9A%E8%AE%AF%E6%9E%B6%E6%9E%84/
開源移動通訊架構與XMPP
http://timyang.net/im/mobile-im-xmpp/
xmpp協議詳解一:xmpp基本概念
http://www.jianshu.com/p/a94749385755
即時通訊協議的選型之XMPP
http://www.biaodianfu.com/xmpp.html
XMPP 協議適合用來做移動 IM 么?
https://segmentfault.com/a/1190000000656509