天天看點

微信終端跨平台元件 mars 系列(二):信令傳輸逾時設計

作者:shockcao

mars 是微信官方使用 C++ 編寫的業務性無關、平台性無關的終端基礎元件,目前在微信 Android、iOS、Windows、Mac、Windows Phone 等多個平台中使用,并正在籌備開源,它主要包含以下幾個獨立的部分:

1、COMM:基礎庫,包括 socket、線程、消息隊列、協程等基礎工具;

2、XLOG:通用日志子產品,充分考慮移動終端的特點,提供高性能、高可用、安全性、容錯性的日志功能;(詳情點選:高性能日志子產品xlog )

3、SDT:網絡診斷子產品;

4、STN:信令傳輸網絡子產品,負責終端與伺服器的小資料信令通道。包含了微信終端在移動網絡上的大量優化經驗與成果,經曆了微信海量使用者的考驗。

本篇文章将為大家介紹 STN(信令傳輸網絡子產品),由于 STN 的複雜性,該子產品将被分解為多個篇章進行介紹,本文主要内容為微信中關于讀寫逾時的思考與設計。

微信信令通信主要使用 TCP/IP 協定,資料經過應用層、傳輸層、網絡層、鍊路層(見圖1)。其中,鍊路層與傳輸層,協定提供了逾時重傳的機制。

微信終端跨平台元件 mars 系列(二):信令傳輸逾時設計

圖1 使用 TCP/IP 協定

在鍊路層,一般使用混合自動重傳請求(即 HARQ)。HARQ 是一種結合 FEC(前饋式錯誤修正)與 ARQ(自動重傳請求)的技術,原理如圖2所示。

微信終端跨平台元件 mars 系列(二):信令傳輸逾時設計

圖2 HARQ 原理

通過使用确認和逾時這兩個機制,鍊路層在不可靠實體裝置的基礎上實作可靠的資訊傳輸。這個方案需要手機和 RNC 都支援,目前在 EDGE、HSDPA、HSUPA、UMTS和 LTE 上都已實作支援。

傳輸層(即 TCP 層)提供可靠的傳輸,然而,TCP 層依賴的鍊路本身是不可靠的,TCP 是如何在不可靠的環境中提供可靠服務的呢?答案是逾時和重傳。TCP 在發送資料時設定一個定時器,當定時器溢出還沒有收到 ACK,則重傳該資料。是以,逾時與重傳的關鍵之處在于如何決定定時器間隔與重傳頻率。

傳統 Unix 實作中,定時器的間隔取決于資料的往返時間(即 RTT),根據 RTT 進行一定的計算得到重傳逾時間隔(即 RTO)。由于網絡路由、流量等的變化,RTT 是經常發生變化的,RTT 的測量也極為複雜(平滑算法、Karn 算法、Jacbson 算法等)。在《TCP/IP詳解》中,實際測量的重傳機制如圖3所示,重傳的時間間隔,取整後分别為1、3、6、12、24、48和多個64秒。這個倍乘的關系被稱為“指數退避”。

微信終端跨平台元件 mars 系列(二):信令傳輸逾時設計

圖3 實際測量的重傳機制

在移動終端中,RTO 的設計以及重試頻率的設計是否與傳統實作一緻呢?對此我們進行了實測,實測資料如下:

圖4所示為OPPO手機TCP逾時重傳的間隔,依次為[ 0.25s,0.5s,1s,2s,4s,8s,16s,32s,64s,64s,64s …]:

微信終端跨平台元件 mars 系列(二):信令傳輸逾時設計

圖4 OPPO 手機 TCP 逾時重傳間隔

而 SamSung 中 TCP 逾時重傳的間隔依次為[0.42s, 0.9s, 1.8s, 3.7s, 7.5s, 15s, 30s, 60s, 120s, 120s …],見圖5。

微信終端跨平台元件 mars 系列(二):信令傳輸逾時設計

圖5 三星手機 TCP 逾時重傳間隔

經過多次實際測試我們可以看出雖然由于不同廠商的 Android 系統實作,RTO 的值可能會有不同的設定,但都基本符合“指數退避”原則。

接下來再看 iOS 系統中,TCP RTO 的實驗資料,圖6所示為實驗中第一次的資料[ 1s,1s,1s,2s,4.5s,9s,13.5s,26s,26s … ]。

微信終端跨平台元件 mars 系列(二):信令傳輸逾時設計

圖6 iOS 系統 TCP RTO 第一次實驗資料

上面的資料看起來并不完全符合指數退避,開始階段的重試會較為頻繁且 RTO 最終固定在 26s 這一較小的值上。

進行第二次測試後發現資料有了新的變化[1s,1s,1s,2s,3.5s,8.5s,12.5s,24s,24s …],如圖7所示。

微信終端跨平台元件 mars 系列(二):信令傳輸逾時設計

圖7 iOS 系統 TCP RTO 第二次實驗資料

RTO 終值由26秒縮減至24秒,最終經過多次測試并未發現 iOS 中 TCP RTO 的規律,但可以看出 iOS 确實采用了較為激進的逾時時間設定,對重試更為積極。

通過上述的調研與實驗,可以發現在 TCP/IP 中,協定棧已經幫助我們進行了逾時與重傳的控制。并且在 Android、iOS 的移動作業系統中進行了優化,使用了更為積極的政策,以适應移動網絡不穩定的特征。

那是否意味着我們的應用層已經不需要逾時與重傳的控制了呢?其實不然。在鍊路層,HARQ 提供的是節點之間每一資料幀的可靠傳輸;在傳輸層,TCP 逾時重傳機制提供的是端與端之間每個 TCP 資料包的可靠傳輸;同理,在微信所處的應用層中,我們仍然需要提供以“請求”為粒度的可靠傳輸。

那麼,應用層的逾時重傳機制應該提供怎樣的服務呢?

首先,我們來看一下應用層重傳的做法。在應用層中,重傳的做法是:斷掉目前連接配接,重建立立連接配接并發送請求。這種重傳方式能帶來怎樣的作用呢?回顧 TCP 層的逾時重傳機制可以發現,當發生逾時重傳時,重傳的間隔以“指數退避”的規律急劇上升。在 Android 系統中,直到16分鐘,TCP 才确認失敗;在 iOS 系統中,直到1分半到3分半之間,TCP 才确認失敗。這些數值在大部分應用中都是不為“使用者體驗”所接受的。是以,應用層的逾時重傳的目标首先應是:

在使用者體驗的接受範圍内,盡可能地提高成功率

盡可能地增加成功率,是否意味着在有限的時間内,做盡可能多的重試呢?其實不然。當網絡為高延遲/低速率的網絡時,較快的應用層重傳會導緻“請求”在這種網絡下很難成功。是以,應用層逾時重傳的目标二:

保障弱網絡下的可用性

TCP連接配接是有固定實體線路的連接配接,當已 Connect 的線路中,如果中間裝置出現較大波動或嚴重擁塞,即使在限定時間内該請求能成功,但帶來的卻是性能低下,反應遲鈍的使用者體驗。通過應用層重連,期待的目标三是:

具有網絡敏感性,快速的發現新的鍊路

我們總結應用層逾時重傳,可以帶來以下作用:

1、減少無效等待時間,增加重試次數:當 TCP 層的重傳間隔已經太大的時候,斷連重連,使得 TCP 層保持積極的重連間隔,提高成功率;

2、切換鍊路:當鍊路存在較大波動或嚴重擁塞時,通過更換連接配接(一般會順帶更換IP&Port)獲得更好的性能。

在TCP層的逾時重傳設計中,逾時間隔取決于RTT,RTT即TCP包往返的時間。同理,在微信的早期設計中,我們分析應用層“請求”的往返時間,将其RTT分解為:

請求發送耗時 - 類比TCP包傳輸耗時;

響應信令接收耗時 - 類比ACK傳輸耗時;

伺服器處理請求耗時 - TCP接收端接收和處理資料包的時間相對固定,而微信伺服器由于信令所屬業務的不同,邏輯處理的耗時會差異明顯,是以無法類比;

等待耗時 - 受應用中請求并發數影響。

是以,我們提出了應用層的總讀寫逾時如圖8所示,最低網速根據不同的網絡取不同的值。

微信終端跨平台元件 mars 系列(二):信令傳輸逾時設計

圖8 應用層的總讀寫逾時

在實際的使用過程中,我們發現這僅僅是一個可用的方案,并不是一個高性能的解決方案:逾時時長的設定使用了差網絡下、完整的完成單次信令互動的時間估值。這使得逾時時間過長,在網絡波動或擁塞時,無法敏感地發現問題并重試。進一步分析可以發現,我們無法預知伺服器回包的大小,是以使用了最大的回包進行估算(微信中目前最大回包可到 128KB)。然而,TCP 傳輸中當發送資料大于 MSS 時,資料将被分段傳輸,分段到達接收端後重新組合。如果伺服器的回包較大,用戶端可能會收到多個資料段。是以,我們可以對首個資料分段的到達時間進行預期,進而提出首包逾時,如圖9所示。

微信終端跨平台元件 mars 系列(二):信令傳輸逾時設計

圖9 首包逾時計算

首包逾時縮短了發現問題的周期,但是我們發現如果首個資料分段按時到達,而後續資料包丢失的情況下,仍然要等待整個讀寫逾時才能發現問題。為此我們引入了包包逾時,即兩個資料分段之間的逾時時間。因為包包逾時在首包逾時之後,這個階段已經确認伺服器收到了請求,且完成了請求的處理,是以不需要計算等待耗時、請求傳輸耗時、伺服器處理耗時,隻需要估算網絡的 RTT。

在目前方案中,使用了不同網絡下的固定 RTT。由于有了“首包已收到”的上下文,使得包包逾時的間隔大大縮短,進而提高了對網絡突然波動、擁塞、突發故障的敏感性,使得應用獲得較高的性能。

在上述的方案中,總讀寫逾時、首包逾時都使用了一些估值,使得這兩個逾時是較大的值。假如我們能獲得實時的動态網速等,我們能獲得更好的逾時機制,如圖10所示。

微信終端跨平台元件 mars 系列(二):信令傳輸逾時設計

圖10 實時動态網速下的逾時估算

但是,理想是豐滿的,現實是殘酷的:

動态網速需要通過工具方法測定,實時性要求高,并且要考慮網絡波動的影響;

伺服器動态耗時需要伺服器下發不同業務信令的處理耗時;

真實回包大小則隻能靠伺服器通知。

上述的三種途徑對用戶端和伺服器都是巨大的流量、性能的消耗,是以動态化這些變量看起來并不可行。

是以,這裡需要換個角度思考動态優化,手機的網絡狀況可以大概地歸為優質、正常、差三種情況,針對三種網絡狀況進行不同程度的調整,也是動态優化的一種手段。這裡選擇優質網絡狀況進行分析:

如何判定網絡狀況好?網速快、穩定,網絡子產品中與之等價的是能夠短時間完成信令收發,并且能夠連續長時間地完成短時間内信令收發。

即使出現網絡波動,也可以預期會很快恢複。

微信終端跨平台元件 mars 系列(二):信令傳輸逾時設計

圖11 優質網絡狀況優化

根據對網絡狀況好的分析,我們可以做出這樣的優化(如圖11所示):

将用戶端網絡環境區分為優良(Excellent)、評估(Evaluating)兩種狀态;

網速快、穩定就是條件1,信令失敗或網絡類型切換是條件2。

進入Exc狀态後,就縮短信令收發的預期,即減小首包逾時時間,這樣做的原因是我們認為使用者的網絡狀況好,可以設定較短的逾時時間,當遇到網絡波動時預期它能夠快速恢複,是以可以盡快逾時然後進行重試,進而改善使用者體驗。

雖然 TCP/IP 協定棧中的鍊路層、傳輸層都已經提供了逾時重傳,保障了傳輸的可靠性。但應用層有着不同的可靠性需求,進而需要額外的應用層逾時重傳機制來保障應用的高性能、高可用。應用層逾時重傳的設計目标,筆者從自身經驗出發,總結為:

在使用者體驗的接受範圍内,盡可能地提高成功率;

保障弱網絡下的可用性;

具有網絡敏感性,快速地發現新的鍊路。

依從這些目标,mars STN 的逾時重傳機制在使用中不斷的精細化演進,使用了包含總讀寫逾時、首包逾時、包包逾時、動态逾時等多種方案的綜合。即使如此,STN 的逾時重傳機制也有着不少的缺點與局限性,例如相對适用于小資料傳輸的信令通道、局限于一來一回的通信模式等。mars STN 也會不斷發現新的問題持續演進,并且所有的演進都将在微信的海量使用者中進行驗證。同時也期待随着 mars STN 的開源,能收獲更多、更廣的經驗交流、問題回報、新想法的碰撞等。

本文來源于:WeMobileDev 微信公衆号