【騰訊Bugly乾貨分享】微信終端跨平臺組件 mars 系列(二) - 信令傳輸超時設計

本文來自於騰訊Bugly公衆號(weixinBugly),未經做者贊成,請勿轉載,原文地址:http://mp.weixin.qq.com/s/9DJxipJaaBC8yC-buHgnTQ程序員

做者簡介: 曹少琨,微信移動客戶端開發工程師,2014年加入騰訊,從事手Q跨平臺移動服務框架 MSF 的開發及優化工做,2015 年轉入微信終端基礎開發組參與網絡組件的開發及維護工做。算法

前言

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

  1. COMM:基礎庫,包括 socket、線程、消息隊列、協程等基礎工具;
  2. XLOG:通用日誌模塊,充分考慮移動終端的特色,提供高性能、高可用、安全性、容錯性的日誌功能;(詳情點擊:高性能日誌模塊xlog
  3. SDT:網絡診斷模塊;
  4. STN:信令傳輸網絡模塊,負責終端與服務器的小數據信令通道。包含了微信終端在移動網絡上的大量優化經驗與成果,經歷了微信海量用戶的考驗。

本篇文章將爲你們介紹 STN(信令傳輸網絡模塊),因爲 STN 的複雜性,該模塊將被分解爲多個篇章進行介紹,本文主要內容爲微信中關於讀寫超時的思考與設計。服務器

讀寫超時與設計目標

TCP/IP中的超時設計

微信信令通訊主要使用 TCP/IP 協議,數據通過應用層、傳輸層、網絡層、鏈路層(見圖1)。其中,鏈路層與傳輸層,協議提供了超時重傳的機制。微信

<center>![](http://img.blog.csdn.net/20161205200455631)</center>網絡

<center>圖1 使用 TCP/IP 協議</center>併發

鏈路層的超時與重傳

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

<center>![](http://img.blog.csdn.net/20161205200539455)</center>socket

<center>圖2 HARQ 原理</center>工具

經過使用確認和超時這兩個機制,鏈路層在不可靠物理設備的基礎上實現可靠的信息傳輸。這個方案須要手機和 RNC 都支持,目前在 EDGE、HSDPA、HSUPA、UMTS和 LTE 上都已實現支持。

傳輸層的超時與重傳

傳輸層(即 TCP 層)提供可靠的傳輸,然而,TCP 層依賴的鏈路自己是不可靠的,TCP 是如何在不可靠的環境中提供可靠服務的呢?答案是超時和重傳。TCP 在發送數據時設置一個定時器,當定時器溢出尚未收到 ACK,則重傳該數據。所以,超時與重傳的關鍵之處在於如何決定定時器間隔與重傳頻率。

傳統 Unix 實現中,定時器的間隔取決於數據的往返時間(即 RTT),根據 RTT 進行必定的計算獲得重傳超時間隔(即 RTO)。因爲網絡路由、流量等的變化,RTT 是常常發生變化的,RTT 的測量也極爲複雜(平滑算法、Karn 算法、Jacbson 算法等)。在《TCP/IP詳解》中,實際測量的重傳機制如圖3所示,重傳的時間間隔,取整後分別爲一、三、六、十二、2四、48和多個64秒。這個倍乘的關係被稱爲「指數退避」。

<center>![](http://img.blog.csdn.net/20161205200628178)</center>

<center>圖3 實際測量的重傳機制</center>

在移動終端中,RTO 的設計以及重試頻率的設計是否與傳統實現一致呢?對此咱們進行了實測,實測數據以下:

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

<center>![](http://img.blog.csdn.net/20161205200713366)</center>

<center>圖4 OPPO 手機 TCP 超時重傳間隔</center>

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

<center>![](http://img.blog.csdn.net/20161205200838788)</center>

<center>圖5 三星手機 TCP 超時重傳間隔</center>

通過屢次實際測試咱們能夠看出雖然因爲不一樣廠商的 Android 系統實現,RTO 的值可能會有不一樣的設定,但都基本符合「指數退避」原則。

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

<center>![](http://img.blog.csdn.net/20161205201824606)</center>

<center>圖6 iOS 系統 TCP RTO 第一次實驗數據</center>

上面的數據看起來並不徹底符合指數退避,開始階段的重試會較爲頻繁且 RTO 最終固定在 26s 這一較小的值上。

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

<center>![](http://img.blog.csdn.net/20161205202013951)</center>

<center>圖7 iOS 系統 TCP RTO 第二次實驗數據</center>

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所示,最低網速根據不一樣的網絡取不一樣的值。

<center>![](http://img.blog.csdn.net/20161205202218604)</center>

<center>圖8 應用層的總讀寫超時</center>

方案二:分步的讀寫超時

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

<center>![](http://img.blog.csdn.net/20161205202752454)</center>

<center>圖9 首包超時計算</center>

首包超時縮短了發現問題的週期,可是咱們發現若是首個數據分段按時到達,然後續數據包丟失的狀況下,仍然要等待整個讀寫超時才能發現問題。爲此咱們引入了包包超時,即兩個數據分段之間的超時時間。由於包包超時在首包超時以後,這個階段已經確認服務器收到了請求,且完成了請求的處理,所以不須要計算等待耗時、請求傳輸耗時、服務器處理耗時,只須要估算網絡的 RTT。

在目前方案中,使用了不一樣網絡下的固定 RTT。因爲有了「首包已收到」的上下文,使得包包超時的間隔大大縮短,從而提升了對網絡忽然波動、擁塞、突發故障的敏感性,使得應用得到較高的性能。

方案三:動態的讀寫超時

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

<center>![](http://img.blog.csdn.net/20161205202949660)</center>

<center>圖10 實時動態網速下的超時估算</center>

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

  • 動態網速須要經過工具方法測定,實時性要求高,而且要考慮網絡波動的影響;
  • 服務器動態耗時須要服務器下發不一樣業務信令的處理耗時;
  • 真實回包大小則只能靠服務器通知。

上述的三種途徑對客戶端和服務器都是巨大的流量、性能的消耗,因此動態化這些變量看起來並不可行。

所以,這裏須要換個角度思考動態優化,手機的網絡情況能夠大概地歸爲優質、正常、差三種狀況,針對三種網絡情況進行不一樣程度的調整,也是動態優化的一種手段。這裏選擇優質網絡情況進行分析:

  • 如何斷定網絡情況好?網速快、穩定,網絡模塊中與之等價的是可以短期完成信令收發,而且可以連續長時間地完成短期內信令收發。
  • 即便出現網絡波動,也能夠預期會很快恢復。

<center>![](http://img.blog.csdn.net/20161205203029783)</center>

<center>圖11 優質網絡情況優化</center>

根據對網絡情況好的分析,咱們能夠作出這樣的優化(如圖11所示):

  • 將客戶端網絡環境區分爲優良(Excellent)、評估(Evaluating)兩種狀態;
  • 網速快、穩定就是條件1,信令失敗或網絡類型切換是條件2。

進入Exc狀態後,就縮短信令收發的預期,即減少首包超時時間,這樣作的緣由是咱們認爲用戶的網絡情況好,能夠設置較短的超時時間,當遇到網絡波動時預期它可以快速恢復,因此能夠儘快超時而後進行重試,從而改善用戶體驗。

總結

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

  • 在用戶體驗的接受範圍內,儘量地提升成功率;
  • 保障弱網絡下的可用性;
  • 具備網絡敏感性,快速地發現新的鏈路。

依從這些目標,mars STN 的超時重傳機制在使用中不斷的精細化演進,使用了包含總讀寫超時、首包超時、包包超時、動態超時等多種方案的綜合。即便如此,STN 的超時重傳機制也有着很多的缺點與侷限性,例如相對適用於小數據傳輸的信令通道、侷限於一來一回的通訊模式等。mars STN 也會不斷髮現新的問題持續演進,而且全部的演進都將在微信的海量用戶中進行驗證。同時也期待隨着 mars STN 的開源,能收穫更多、更廣的經驗交流、問題反饋、新想法的碰撞等。

本文首次發表在 CSDN《程序員》雜誌2016年12月期,已獲受權,版權歸《程序員》全部,未經容許請勿轉載。

更多精彩內容歡迎關注騰訊 Bugly的微信公衆帳號:

騰訊 Bugly是一款專爲移動開發者打造的質量監控工具,幫助開發者快速,便捷的定位線上應用崩潰的狀況以及解決方案。智能合併功能幫助開發同窗把天天上報的數千條 Crash 根據根因合併分類,每日日報會列出影響用戶數最多的崩潰,精準定位功能幫助開發同窗定位到出問題的代碼行,實時上報能夠在發佈後快速的瞭解應用的質量狀況,適配最新的 iOS, Android 官方操做系統,鵝廠的工程師都在使用,快來加入咱們吧!

相關文章
相關標籤/搜索