轉:移動端即時通信系統實踐

移動端即時通信系統實踐

2016-04-19 廖錦幸 iOS開發探索

在信息高度發達的今天,IM基本上已經成爲了一個社交應用的標配。本文將以一個移動開發者的視角,探討移動端即時通信系統的技術選型和關鍵要點。html

 

1 即時通信系統的需求java

任何技術系統都來源於真實業務的需求,作架構設計以前應該先設定好目標。做爲一個即時通信應用,能夠參考微信的使用體驗,你須要保證如下特性:數據庫

1,實時。消息的接收端應該可以及時收到並處理消息。緩存

2,不丟。須要保證全部的消息都順利送達。安全

3,不重。重複的消息對用戶來講是一種糟糕的體驗。性能優化

4,保序。只要順序一亂,消息根本沒發看。服務器

5,節能。流量難得,電量難得,能省則省。微信

6,安全。若是涉及敏感數據,安全必須重視。網絡

7,流暢。卡頓的應用是不會被用戶接受的。架構

 

2 關鍵技術點

爲了保證消息的實時性,有兩種思路:

1,長輪詢方式,高頻率地從服務端拉取新消息。這種方式其實就是傳統的請求-響應模型,如今不少體育文字直播軟件也採起這種方式。這種方法雖然簡單,但有不少缺點。一是會產生不少請求,這對服務器的壓力和用戶的流量都是浪費。二是消息仍然不夠及時,不考慮傳輸時間,最長的延遲就是輪詢的間隔。

2,消息的生產者主動推送消息。這應該是更好的選擇,能夠解決長輪詢的缺點。咱們的即時通信系統也會採用這種方式。使用長鏈接,並且鏈接必須是穩定可靠的,才能確保消息的實時性。

 

2.1 數據通訊協議

服務端與客戶端之間須要協商好數據格式,這是數據傳輸和數據處理的基礎。協議的設計須要着重考慮第一節提到幾點需求。

XMPP和MQTT是當前比較成熟的兩種消息協議。若是能較好地處理你的業務需求,就沒有必要重複造輪子。有不少企業的業務有特殊需求,能夠考慮根據實際狀況自定義協議,從頭開始顯然是不現實的,能夠參考已經成熟的協議再作設計和開發。具體協議內容在此不詳細展開,只作優劣的比較。

 

2.1.1 XMPP

XMPP是一種以XML爲基礎的開放式即時通信協議。

XMPP的優勢是安全,SASL及TL等技術的可靠安全性已內置於核心XMPP技術規格中。

XMPP 協議的最主要的一點就是開放,不論是協議、客戶端,仍是 Server 端,都有成熟的實現方案。

基於XML,它天生擁有很強的靈活性,能夠在覈心協議之上方便地進行定製化。Google Talk就是採用這種協議。

可是XMPP的缺點也很明顯。首先,XMPP協議的方式被編碼爲一個單一的長的XML文件,所以沒法提供修改二進制數據。其次,XML 有大量的標籤冗餘信息,網絡流量的 70% 都消耗在 XMPP 協議層了,這在移動互聯網時代,流量和電量是一個不可忽視的消耗。

 

2.1.2 MQTT

MQTT協議是由IBM提出的基於發佈/訂閱模型的消息傳輸協議,相比於XMPP,它顯得很是輕量小巧,協議內容包括固定頭部+可變頭部+消息體,最下的狀況下頭部只須要兩個字節,在傳輸開銷上有着巨大的優點,能夠節省流量和電量。

MQTT能夠保證消息的可靠性,它包括三種不一樣的服務質量(最多隻傳一次、最少被傳一次、一次且只傳一次),若是客戶端意外掉線,可使用「遺願」發佈一條消息,同時支持持久訂閱。

 

XMPP使用XML,是一個歷史的選擇,在如今移動應用的場景下,我的更加推薦MQTT。據瞭解,很多企業,包括作IM SDK的廠商,也是在MQTT的基礎上進行自定義的擴展和修改。

 

2.2 鏈接的穩定性

移動互聯網的場景下,網絡環境常常變化,須要保證鏈接是穩定的。

2.2.1 心跳

最經典的作法就是使用心跳,實時地檢測鏈接狀態。一般是客戶端每隔一小段時間向服務器發送一個數據包,通知服務器本身仍然在線,並傳輸一些可能必要的數據。若是在必定時間內服務器沒有響應,則認爲鏈接可能已經斷開,從新嘗試鏈接。

僞代碼以下:

上述代碼的心跳間隔是固定的。因爲心跳包也是會消耗流量的,所以應該找到一個理想的心跳週期,在能敏銳地察覺鏈接變化的前提下,儘可能大地增長週期間隔。所以能夠作一個優化,是使心跳間隔動態增長。

 

2.2.2 多鏈接嘗試

(1)多鏈接嘗試

考慮到不一樣地區不一樣網絡運營商的狀況下,用戶可能由於網絡限制,鏈接不上咱們的服務或者比較慢。咱們在實踐中就發現,某些網絡運營商將某些端口封禁了,致使部分用戶鏈接不上服務。爲了解決這個問題,能夠提供多個ip和多個端口,客戶端在鏈接某個ip比較慢的狀況下,能夠進行輪詢,切換到一個更快的ip。

(2)長鏈接與短鏈接結合

這只是一條退路,而不是常規武器。

在長鏈接實在鏈接不上的狀況下,能夠考慮作降級,使用短鏈接長輪詢的方式進行替代。

 

2.3 服務質量

系統的設計每每存在着取捨和妥協。正如TCP比UDP更加可靠,但它的負載會更高。

在即時通信系統中也存在着取捨的問題,是追求極速送達,仍是在傳輸上作可靠性的保證,確保不丟不重?不一樣的業務類型可能須要不一樣的服務質量,MQTT協議提供了三種服務質量,能夠做爲參考:

QoS 0: 至多發送一次,發送即丟棄。沒有確認消息,也不知道對方是否收到。針對的消息不重要,丟失也無所謂。

QoS 1: 至少發送一次。發送以後,會等待接收方ack確認。在必定時間以內,若是沒有收到ack,則會再發一次,一直到接收方收到。重發的消息會在頭部有dup標示。這種QoS能夠保證消息不丟,但接收方可能會有重複消息,須要作去重。以下圖所示:

QoS 2:有且僅有一次。能夠保證不丟不重,可是通訊壓力高,須要屢次握手。以下圖所示:

 

3,客戶端實現

3.1 消息處理

發送消息比較簡單,只須要往某一個topic發佈便可。

接收消息的流程以下:

收消息:客戶端須要保持一個長鏈接,而且確保鏈接穩定,如上章節所示。

消息過濾:若是發送端不能確保消息不重(如mqtt中QoS爲0或1),客戶端須要作去重,所以消息須要有一個惟一的id。

消息合併和分發:在實際使用場景中,每每有各類各樣的消息類型(如聊天消息、系統通知等),對同一類型的消息能夠作合併,以加快後續消息處理速度。而不一樣類型的消息則分發到各自的處理器當中,如存儲到本地數據庫,通知頁面更新等)

UI更新:客戶端通常是使用列表來展現消息(iOS中是UITableView,Android中是ListView),而列表的數據量可能很大,數據源更新頻率也可能很頻繁,所以須要對列表作性能優化,以確保用戶體驗。以iOS爲例,使用Instruments監控性能瓶頸的地方,對內存佔用和CPU佔用大戶進行優化。肯定問題後,經常使用的技巧有:對cell高度作緩存;簡化UI層次結構;避免大量的離屏渲染;減小混合圖層;等等。對症下藥,各個擊破。

 

3.2 其餘

IM應用中,還有不少經常使用的實現需求,例如表情鍵盤,圖片語音等多媒體的存儲和下載隊列等。但這不在系統實現的範疇中,未來後有文章進行詳細闡述。

 

 

參考:

https://en.wikipedia.org/wiki/XMPP

http://www.blogjava.net/yongboy/archive/2014/02/15/409893.html

相關文章
相關標籤/搜索