IM(InstantMessaging 即時通信)做爲一項基礎功能,不少APP都有,好比:手機QQ、微信、易信、釘釘、飛信、旺旺、咚咚、陌陌等。而IM如同咱們平常生活中的水和電同樣,必不可少,也是不少「社交」類APP必不可少的基礎功能,而上面這些APP裏面,微信最爲出色。html
若是做爲一名創業者須要用到IM的功能,我建議是直接使用第三方提供的服務,好比:易信(網易的童鞋們記得要給我打賞哇,我看過它提供的DEMO和服務,確實很贊~),爲何不本身開發?你有單聊那就須要羣聊吧,而在移動互聯網時代,由於移動互聯網的特色,致使對技術的門檻比PC上的IM要高很多,而IM作爲基礎功能又相當重要,傳聞不少公司內部是不容許使用QQ的(緣由是怕由於信息外泄,360確定是不用QQ的,具體用啥我也不清楚了)。扯了這麼多,準備切入正題...linux
一、弱網絡
二、對電量、流量敏感;
若是你的APP提供的IM服務,一是慢、常常丟失消息二是還特別費流量、電量,你以爲用戶有什麼理由不卸載你的APP呢?而光解決弱網絡這個問題就是一個比較深的坑,因此沒有必定的技術積累或是資源投入仍是建議不要往這裏面跳了。web
一、消息收、發儘量快(不快、不實時就不叫即時通信了);
二、不能丟失消息(你把消息都丟失了,誰還敢用,跟錢存銀行錢可能會丟差很少);後端
APP上的IM傳輸協議以TCP主爲,同時支持HTTP,而PC上的QQ主要採用UDP協議(歷史緣由),手機QQ是否也採用了UDP還不太肯定。若是要實現像微信同樣,支持web版,能夠用HTTP/HTTPS來實現comet或者直接使用websocket(低版本的瀏覽器不支持)瀏覽器
幾個原則:
一、傳輸信息體積儘量小,越小才能傳的越快,失敗重傳的可能性也越低;
二、傳輸的數據是安全、可靠的,你不能明文傳輸吧,而序列化、反序列化又會影響你的性能(Java在序列化、反序列化上性能問題尤其突出);
三、易於擴展、可維護(產品加一項功能,不能說後端更新了,APP端沒法解析就會更種報錯,沒法使用);安全
經常使用的聊天協議:
一、XMPP
基於XML的消息協議,調試方便,抓到XML能大概看懂什麼意思,缺點就是太臃腫了,雖然方便擴展,可是太費流量,強烈不建議使用,用它實現的APP收發消息不會快到哪去;
二、自定義的二進制協議
二進制確定是比XML的體積要小的,建議是自定義的二進制協議 + protobuf微信
協議的定製的話,能夠參考MySQL或者Redis的協議格式,這裏給出一個參考的格式(類MySQL的):
數據包長度(4 byte)+ 協議頭(2 byte)+ 協議版本(2 byte) + 錯誤碼(2 byte)+ 回執碼(2 byte)+ 消息體(data body)websocket
爲了安全和性能方面的平衡,能夠考慮將消息體進行簡單的加密處理(能夠簡單的將指定的位置的字節進行順序調整,好比第一位與最後一位進行對調均可以)。這樣在傳輸的過程當中不用反序列化就很容易知道當前這條消息它的消息頭是什麼,提高一些業務邏輯的處理效率。客戶端在接收數據時,爲了解決粘包的老是,確定會有一個緩衝池(多是環形緩衝池),而數據包的長度能避免粘包的問題。網絡
鏈接層(主要維護客戶端的鏈接與消息的中轉)
邏輯層(用戶會話的驗證,業務邏輯驗證,消息存取,異步的消息隊列)
持久層(數據的存儲,熱冷數據,災備)架構
基本的消息收發流程:發 -> 存 -> 推送通知 -> 拉取消息,同時消息採用基於版本號的設計來保證消息的順序。
注:圖片來自從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
後面二塊非我所長,我就不具體深刻寫了,重點可參考微信的那篇文章。針對我的,微信爲每個人同步數據時產生一個惟1、遞增的序列號,在高併發的場景下,這個又是如何設計的呢,有興趣能夠參考這篇文章,講的很是詳細:萬億級調用系統:微信序列號生成器架構設計及演變