當前位置: 妍妍網 > 碼農

回憶殺!十年前的微信訊息收發架構長啥樣?

2024-06-19碼農



目錄

一、背景

二、訊息收發架構

三、訊息防遺失機制

四、總結

2023 年,微信及 WeChat 的 DAU(月活使用者)達到 13.4 億,微信已經是很多人工作、生活中不可或缺的一個環節。從 2011 年 1 月 21 日上線至今,微信已經走過了 13 個年頭,其背後的技術基座與架構也發生了巨大的變化。

一、背景

微信誕生於 QQMail 團隊,初始的整個微信後台架構都帶著濃重的信箱氣息,訊息收發 架構作為微信最為核心的部份,同樣是基於信箱的儲存轉發機制演變而來。

微信定位為即時通訊軟體,對訊息的收發有2個基本的要求:

  • 訊息盡可能的即時送達。

  • 不丟訊息。

  • 在信箱的儲存轉發機制上做了改良後,微信的訊息收發實作了以上2個基本要求。

    二、訊息收發架構

    1.訊息發送架構

    首先透過手機 A 給手機 B 發送一條微信訊息來看訊息發送的整體架構是怎樣的,如圖1所示:

    微信訊息發送在整體架構上可以分為2個部份:

    1)手機A發送訊息到伺服器 (圖1中1,2,3部份)

    1:手機A發送發訊息請求到接入層 ConnnectSvr;

    2:接入層收到請求後,將請求轉到邏輯層 SendSvr 進行處理;

    3:邏輯層處理完各種邏輯(如反垃圾,黑名單等等)之後,將訊息存入儲存層 MsgStore。

    2)伺服器發送通知到手機B (圖1中4,5.1,5.2,6,7部份)

    4:邏輯層 SendSvr 將給手機 B 的新訊息到達通知發送到通知處理伺服器 PushSvr;

    5.1:PushSvr 查詢手機 B 在接入層所在長連線的 ConnectSvr,並將通知發給該 ConnectSvr;

    5.2:PushSvr 發送一個 Push tips 給手機作業系統自建的第三方 Push 系統(如蘋果的 ApnsPush,微軟的 WPPush,黑莓的 BBPush 等)。像蘋果的 IOS 系統,在 APP 結束到後台10分鐘後就會釋放掉該 APP 所持有的所有資源(如 CPU,網路,記憶體等),導致之前建立的長連線通道也會一並斷掉,此時透過5.1的方式進行通知是不可達的,所以還需要依賴與蘋果自身的 apns 通道來達到即時通知的目的;

    6:接入層 ConnnectSvr 透過手機 B 建立的長連線通道將新訊息達到通知發送給手機 B;

    7:第三方 Push 伺服器透過自建的 Push 透過發送 Push tips 到手機 B。

    2.訊息接收架構

    手機 B 在收到新訊息到達通知後進行訊息收取的整體架構如圖2所示:

    訊息收取的流程主要分為3個步驟:

  • 手機 B 發起收取訊息的請求到接入層伺服器 ConnnectSvr;

  • 接入層伺服器 ConnnectSvr 接到請求後轉給邏輯層伺服器 ReceiveSvr 進行處理;

  • ReceiveSvr 從儲存層 MsgStore 中獲取到需要下發的訊息。

  • 3.小結

    以上訊息收發架構可以保證手機 A 在發出訊息 100ms 級別內讓手機 B 收取到該條訊息。當然 對於結束後台的蘋果 IOS 使用者,在蘋果的 apns 伺服器正常的情況下,也可以保證在秒級別內通知到手機 B 點開 APP 進入前台來收取訊息。

    三、訊息防遺失機制

    訊息收發架構保證了訊息收發雙方能夠及時收發訊息,但該架構不能保證訊息在傳輸過程中不發生丟棄。當然為了達到任意一條訊息都不丟的狀態,最簡單的方案是手機端對收到的每條訊息都給伺服器進行一次 ack 確認,但該方案在手機端和伺服器之間的互動過多,並且也會遇到在弱網路情況下 ack 遺失等問題。為了完美的做到訊息不丟,微信訊息系統對訊息收發引入了 sequence 機制。

    1.sequence 機制

  • 每個使用者都有42億的 sequence 空間(從1到 UINT_MAX),從小到大連續分配;

  • 每個使用者的每條訊息都需要分配一個 sequence;

  • 伺服器儲存有每個使用者已經分配到的最大 sequence;

  • 手機端儲存有已收取訊息的最大 sequence。

  • 2.訊息收取 sequnece 確認機制

    當伺服器和手機端都擁有了一個 sequence 之後,伺服器和手機端之間就可以根據兩者 sequence 的差異來收取訊息,同時保證手機端未收取下去的訊息最終能夠收取下去。具體流程如圖3表示:

  • 根據伺服器和手機端之間 sequence 的差異,可以很輕松的實作增量下發手機端未收取下去的訊息。

  • 對於在弱網路環境差的情況,丟包情況發生機率是比較高的,此時經常會出現伺服器的回包不能到達手機端的現象。由於手機端只會在確切的收取到訊息後才會更新原生的 sequence,所以即使伺服器的回包丟了,手機端等待超時後重新拿舊的 sequence 上伺服器收取訊息,同樣是可以正確的收取未下發的訊息。

  • 由於手機端儲存的 sequence 是確認收到訊息的最大 sequence,所以對於手機端每次到伺服器來收取訊息也可以認為是對上一次收取訊息的確認。一個帳號在多個手機端輪流登入的情況下,只要伺服器儲存手機端已確認的 sequence,那就可以簡單的實作已確認下發的訊息不會重復下發,不同手機端之間輪流登入不會收到其他手機端已經收取到的訊息。

  • 如圖4所示,假如手機 A 拿 Seq_cli = 100 上伺服器收取訊息,此時伺服器的 Seq_svr = 150,那手機 A 可以將 sequence 為[101 - 150]的訊息收取下去,同時手機 A 會將原生的 Seq_cli 置為150。

    如圖5所示,手機 A 在下一次再次上來伺服器收取訊息,此時 Seq_cli = 150,伺服器的 Seq_svr = 200,那手機 A 可以將 sequence為[151 - 200]的訊息收取下去。

    如圖6所示,假如原手機 A 使用者換到手機 B 登入,並使用 Seq_cli = 120 上伺服器收取訊息,由於伺服器已經確認 sequence <= 150 的訊息已經被手機收取下去了,故不會再返回 sequence 為[121 - 150]的訊息給手機 B,而是將 sequence 為[151 - 200]的訊息下發給手機 B。

    這裏雖然 sequence 為[151 - 200]的訊息有可能是被手機 A 和手機 B 都收取到,但由於手機 A 在收到 sequence 為[151 - 200]的訊息時並沒有給伺服器進行確認或者這些訊息手機 A 壓根就沒有收取到,所以為了防止訊息遺失,sequence 為[151 - 200]的訊息也是需要下發給手機 B 的。

    四、總結

    以上簡單描述了微信訊息收發的架構,該架構實作了即時通訊軟體對訊息收發所需的兩個基本要求:

  • 訊息盡可能的即時送達

  • 不丟訊息

  • 以上,是 2014 年微信古早時期的訊息收發架構的基本介紹,時過境遷,微信的訊息收發架構已經發生了巨大的變化,但我們還是可以從中看到技術演變的價值與力量。

    程式設計師最大的成就與幸福,或許就是自己的程式碼跑在千萬人的裝置上,默默支撐著海量的需求。

    作者丨 黃清

    來源丨公眾號:騰訊雲開發者(ID:QcloudCommunity)

    dbaplus社群歡迎廣大技術人員投稿,投稿信箱: [email protected]