移動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)

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

簡單的收發架構

連接層(主要維護客戶端的連接與消息的中轉)
邏輯層(用戶會話的驗證,業務邏輯驗證,消息存取,異步的消息隊列)
持久層(數據的存儲,熱冷數據,災備)

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

注:圖片來自從0到1:微信后台系統的演進之路

=== 關於連接層
陌陌之前對外的PPT里講到單台壓測連接數達到70W,這個跟配置、帶寬有很大的關系,而蘑菇街的技術博客提到他們單機並發連接10萬用戶,我覺得單台並發10萬相對靠譜一些。

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

而服務端如何及時的清理half-open的連接呢
一種用輪詢的方式,每一個連接發消息過來時更新最后收到心跳包的時間,每一少都定時檢測所有的連接,超時了就主動斷開連接,因為要循環所有連接所以系統性能受影響比較大。
另外一各就是每一個連接都有一個定時器,超時了自動就斷開了,但這會導致系統的資源消耗過高,十萬個連接就得有十萬個定時器,明顯不合理嘛。
還有一種就是時間輪片(Timing Wheel),詳情可參考這里:基於時間輪 (Timing-Wheel) 方式實現的定時器

而關於連接這一塊的優化,可以參考騰訊雲提供的維納期服務
https://www.qcloud.com/product/wns.html

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM