天天看點

移動APP的IM背景架構淺析

IM(InstantMessaging 即時通訊)作為一項基礎功能,很多APP都有,比如:手機QQ、微信、易信、釘釘、飛信、旺旺、咚咚、陌陌等。而IM如同我們日常生活中的水和電一樣,必不可少,也是很多“社交”類APP必不可少的基礎功能,而上面這些APP裡面,微信最為出色。

如果作為一名創業者需要用到IM的功能,我建議是直接使用第三方提供的服務,比如:易信(網易的童鞋們記得要給我打賞哇,我看過它提供的DEMO和服務,确實很贊~),為什麼不自己開發?你有單聊那就需要群聊吧,而在移動網際網路時代,因為移動網際網路的特點,導緻對技術的門檻比PC上的IM要高不少,而IM做為基礎功能又至關重要,傳聞很多公司内部是不允許使用QQ的(原因是怕因為資訊外洩,360肯定是不用QQ的,具體用啥我也不清楚了)。扯了這麼多,準備切入正題...

移動網際網路的一些特性:

1、弱網絡

2、對電量、流量敏感;

如果你的APP提供的IM服務,一是慢、經常丢失消息二是還特别費流量、電量,你覺得使用者有什麼理由不解除安裝你的APP呢?而光解決弱網絡這個問題就是一個比較深的坑,是以沒有一定的技術積累或是資源投入還是建議不要往這裡面跳了。

IM的基本原則:

1、消息收、發盡可能快(不快、不實時就不叫即時通訊了);

2、不能丢失消息(你把消息都丢失了,誰還敢用,跟錢存銀行錢可能會丢差不多);

網絡傳輸協定的選擇

APP上的IM傳輸協定以TCP主為,同時支援HTTP,而PC上的QQ主要采用UDP協定(曆史原因),手機QQ是否也采用了UDP還不太确定。如果要實作像微信一樣,支援web版,可以用HTTP/HTTPS來實作comet或者直接使用websocket(低版本的浏覽器不支援)

消息協定的選擇

幾個原則:

1、傳輸資訊體積盡可能小,越小才能傳的越快,失敗重傳的可能性也越低;

2、傳輸的資料是安全、可靠的,你不能明文傳輸吧,而序列化、反序列化又會影響你的性能(Java在序列化、反序列化上性能問題尤為突出);

3、易于擴充、可維護(産品加一項功能,不能說後端更新了,APP端無法解析就會更種報錯,無法使用);

常用的聊天協定:

1、XMPP

基于XML的消息協定,調試友善,抓到XML能大概看懂什麼意思,缺點就是太臃腫了,雖然友善擴充,但是太費流量,強烈不建議使用,用它實作的APP收發消息不會快到哪去;

2、自定義的二進制協定

二進制肯定是比XML的體積要小的,建議是自定義的二進制協定 + protobuf

協定的定制的話,可以參考MySQL或者Redis的協定格式,這裡給出一個參考的格式(類MySQL的):

資料包長度(4 byte)+ 協定頭(2 byte)+ 協定版本(2 byte) + 錯誤碼(2 byte)+ 回執碼(2 byte)+ 消息體(data body)

為了安全和性能方面的平衡,可以考慮将消息體進行簡單的加密處理(可以簡單的将指定的位置的位元組進行順序調整,比如第一位與最後一位進行對調都可以)。這樣在傳輸的過程中不用反序列化就很容易知道目前這條消息它的消息頭是什麼,提升一些業務邏輯的處理效率。用戶端在接收資料時,為了解決粘包的總是,肯定會有一個緩沖池(可能是環形緩沖池),而資料包的長度能避免粘包的問題。

簡單的收發架構

連接配接層(主要維護用戶端的連接配接與消息的中轉)

邏輯層(使用者會話的驗證,業務邏輯驗證,消息存取,異步的消息隊列)

持久層(資料的存儲,熱冷資料,災備)

基本的消息收發流程:發 -> 存 -> 推送通知 -> 拉取消息,同時消息采用基于版本号的設計來保證消息的順序。

移動APP的IM背景架構淺析

注:圖檔來自從0到1:微信背景系統的演進之路

=== 關于連接配接層

陌陌之前對外的PPT裡講到單台壓測連接配接數達到70W,這個跟配置、帶寬有很大的關系,而蘑菇街的技術部落格提到他們單機并發連接配接10萬使用者,我覺得單台并發10萬相對靠譜一些。

因為移動網絡的不穩定性,比如iPhone來個電話或者按了電源鍵幾秒後,網絡都會中斷,會導緻socket的重連同時也産生非常多的TCP half-open,而防止TCP的half-open通常采用心跳包的機制,而心跳包的頻率也是非常有講究,假設使用移動網絡,頻率高了費流量不說,還會導緻信令風暴【參見 從微信信令風暴談起】。而時間太長就會導緻服務端過多的連接配接消耗。而心跳的頻率具體應該定為多少,建議的話20s左右,具體的時間還跟ISP營運商的政策有關,一條通道多長時間不用就要被回收掉,而如果重建立立一條通道這個時間就會變的比較漫長。

而服務端如何及時的清理half-open的連接配接呢

一種用輪詢的方式,每一個連接配接發消息過來時更新最後收到心跳包的時間,每一少都定時檢測所有的連接配接,逾時了就主動斷開連接配接,因為要循環所有連接配接是以系統性能受影響比較大。

另外一各就是每一個連接配接都有一個定時器,逾時了自動就斷開了,但這會導緻系統的資源消耗過高,十萬個連接配接就得有十萬個定時器,明顯不合理嘛。

還有一種就是時間輪片(Timing Wheel),詳情可參考這裡:基于時間輪 (Timing-Wheel) 方式實作的定時器

移動APP的IM背景架構淺析

而關于連接配接這一塊的優化,可以參考騰訊雲提供的維納期服務

https://www.qcloud.com/product/wns.html

後面二塊非我所長,我就不具體深入寫了,重點可參考微信的那篇文章。針對個人,微信為每一個人同步資料時産生一個唯一、遞增的序列号,在高并發的場景下,這個又是如何設計的呢,有興趣可以參考這篇文章,講的非常詳細:萬億級調用系統:微信序列号生成器架構設計及演變

移動APP的IM背景架構淺析