1. 程式人生 > >自適應心跳機制

自適應心跳機制

原文連結:http://www.52im.net/thread-120-1-1.html

本文由微信開發團隊人員編寫,轉自 WeMobileDev,感謝。


一 引言


在2013年11月中旬時,因為基礎元件組人手緊張,Leo安排我和春哥去廣州輪崗支援。

剛到廣州的時候,Ray讓我和春哥對Line和WhatsApp的心跳機制進行分析。我和春哥抓包測試了差不多兩個多禮拜,在我們基本上摸清了Line和WhatsApp的心跳機制後,Ray才告訴我們真正的任務——對微信的固定心跳進行優化,並告訴我們這不是一件容易的事情。

於是我和春哥開始構思第一個方案,我們開始想用統計的方法來解決問題,當我們拿著第一個方案和Ray討論時,發現不能優雅應對Ray的所有提問:

  • 1、測試環境的準確性,失敗到底是因為網路的特性導致還是因為使用者當前的環境變化導致的暫時失敗。
  • 2、臨界值界定,如果方案選中的心跳值是臨界值,我們該怎麼辦。

Ray和元件組同事在網路方面有極其豐富的經驗,雖然他沒有給我們指出明確的方向,但提出的問題幫助我們更快的補齊需要面對的核心問題。這兩個問題讓我和春哥意識到如果能很好的解決,就可以給出一個比較好的心跳方案。第一個問題我和春哥開始就意識到,第二個問題我們確實在一開始時疏忽了。但直接解決這兩個問題確實不容易,這著實讓我和春哥迷茫了幾天,有兩三天在紡園我都沒怎麼睡著,因為想不到更好的方法。

直到有一天思路發生了一些轉變,既然最優解比較複雜,為什麼不繞過去,使用有損服務理念找次優解呢。讓複雜的事情簡單化,好了,想到這裡突然有一種撥開雲霧的感覺。

二 大體思路


  • a)延遲心跳測試法:這是測試結果準確的前提保障,我們認為長連線建立後連續三次成功的短心跳就可以很大程度的保證下一次心跳環境是正常的。
  • b)成功一次認定,失敗連續累積認定:成功是絕對的,連續失敗多次才可能是失敗。
  • c)臨界值避免:我們使用比計算出的心跳稍微小一點的值做為穩定心跳避免臨界值。
  • d)動態調整:即使在一次完整的智慧心跳計算過程中,我們沒有找到最好的值,我們還有機會來進行校正。

三 拍板方案


當我和春哥想出第二個簡單易行的方案後,我們心裡就很有底了,去找Ray討論,Ray聽完後一次通過,然後Ray約了Harvey,給Harvey講完後,Harvey說聽起來可以,可以試試。

然後就開始動手,分析競品加確定方案花了差不多兩個月。寫心跳的主要程式碼,只花了一天時間,我記得那天是年會後的一天。回過頭來再看這個方案花費的時間還是值得的,後來灰度的統計資料顯示,70%使用者都可以達到我們的心跳上限。


搞完智慧心跳後一段時間在廣州沒事幹,我就跟Ray商量,Ray讓我去測試下WebView的效能瓶頸。然後我跟周斯基一起來做這件事,搞完了安卓客戶端WebView效能瓶頸測試後,因為懷孕的老婆一個人在深圳,領導就安排我先回深圳了。春哥堅守著把GCM部分完成後才回深圳。

等我們的心跳版本正式釋出後,一年前我在公司km上分享了智慧心跳方案,吸引不少做push的同事加入了討論,感覺這方面的交流還是很有必要的。

四 方案目標


設計此方案的主要目標是,在儘量不影響使用者收訊息及時性的前提下,根據網路型別自適應的找出保活信令TCP連線的儘可能大的心跳間隔,從而達到減少安卓微信因心跳引起的空中通道資源消耗,減少心跳Server的負載,以及減少部分因心跳引起的耗電。

主要方法是參考WhatsApp和Line中有價值的做法,結合影響TCP連線壽命的因素,實現Android微信後臺自適應心跳演算法。

* 有關WhatsApp、Lin的訊息推送策略請參考文章《移動端IM實踐:WhatsApp、Line、微信的心跳策略分析》;
* 有關GCM的研究結論請參考文章《移動端IM實踐:谷歌訊息推送服務(GCM)研究(來自微信團隊)》。

五 方案需考慮到影響連線壽命的思素


在Android下,不管是GCM,還是微信,都是通過TCP長連線來進行訊息收發的,TCP長連線存活,訊息收發就及時,所以要對影響TCP連線壽命的因素進行研究。

1、NAT超時

大部分移動無線網路運營商都在鏈路一段時間沒有資料通訊時,會淘汰 NAT 表中的對應項,造成鏈路中斷(NAT超時的更多描述見附錄9.1)。NAT超時是影響TCP連線壽命的一個重要因素(尤其是國內),所以客戶端自動測算NAT超時時間,來動態調整心跳間隔,是一個重要的優化點。

2、DHCP的租期(lease time)

目前測試發現安卓系統對DHCP的處理有Bug,DHCP租期到了不會主動續約並且會繼續使用過期IP,這個問題會造成TCP長連線偶然的斷連。(租期問題的具體描述見附錄9.2)。 

3、網路狀態變化

手機網路和WIFI網路切換、網路斷開和連上等情況有網路狀態的變化,也會使長連線變為無效連線,需要監聽響應的網路狀態變化事件,重新建立Push長連線。

六 心跳範圍選擇


1、前後臺區分處理:
為了保證微信收訊息及時性的體驗,當微信處於前臺活躍狀態時,使用固定心跳。微信進入後臺(或者前臺關屏)時,先用幾次最小心跳維持長連結。然後進入後臺自適應心跳計算。這樣做的目的是儘量選擇使用者不活躍的時間段,來減少心跳計算可能產生的訊息不及時收取影響。

2、後臺自適應心跳選擇區間:
可根據自身產品的特點選擇合適的心跳範圍。

以下是狀態轉換示意圖:
移動端IM實踐:實現Android版微信的智慧心跳機制_0.jpeg 

七 自適應心跳演算法量化描述


因為每個網路的NAT時間可能不一致。所以需要區分計算,資料網路按subType做關鍵字,WIFI按WIFI名做關鍵字。對穩定的網路,因為NAT老化時間的存在,在自適應計算態的時候,暫設計以下步驟在當前心跳區間逼近出最大可用的心跳。

a)變數說明:

  • [MinHeart,MaxHeart]——心跳可選區間。
  • successHeart——當前成功心跳,初始為MinHeart
  • curHeart——當前心跳初始值為successHeart
  • heartStep——心跳增加步長
  • successStep——穩定期後的探測步長

b)最大值探測步驟(自適應心跳計算流程):

移動端IM實踐:實現Android版微信的智慧心跳機制_QQ20160303-0.png 

自適應心跳計算流程如上圖所示,經過該流程,會找到必然使心跳失敗的curHeart(或者MaxHeart),為了保險起見,我們選擇比前一個成功值稍微小一點的值作為後臺穩定期的心跳間隔。

影響手機網路測試的因素太多,為了儘量保證測試結果的可靠性,我們使用延遲心跳測試法。在我們重新建立TCP連線後,先使用  短心跳連續成功三次,我們才認為網路相對穩定,可以使用curHeart進行一次心跳測試。圖4-2顯示了一次有效心跳測試過程。圖4-3顯示了在沒有達到穩定網路環境時,我們會一直使用固定短心跳直到滿足三次連續短心跳成功。

使用延遲心跳測試的好處是,可以剔除偶然失敗,和網路變化較大的情況(如地鐵),使測試結果相對可靠(五次延遲測試確定結論)。同時在網路波動較大的情況,使用短心跳,保證收取訊息相對及時。

c)執行時的動態調整策略(已經按測算心跳穩定值後)

NAT超時值算出來後,在維持心跳的過程中的策略。
-  無網路、網路時好時壞、偶然失敗、NAT超時變小:
   在後臺穩定期發生心跳發生失敗後,我們使用延遲心跳測試法測試五次。如果有一次成功,則保持當前心跳值不變;如果五次測試全失敗,重新計算合理心跳值。該過程如圖4-4所示,有一點需要注意,每個新建的長連線需要先用短心跳成功維持3次後才用successHeart進行心跳。後臺穩定態動態調整心跳策略如下圖:
移動端IM實踐:實現Android版微信的智慧心跳機制_QQ20160303-1.png 

-  NAT超時變大:
   以周為週期,每週三將後臺穩定態調至自適應計算態,使用心跳延遲法往後探測心跳間隔。

-  successHeart是NAT超時臨界值:
   因為我們現在選擇的是一個比successHeart稍小的值作為穩定值,所以在計算過程中可以避開臨界值。當運營商在我們後臺穩定期將NAT超時調整為我們當前計算值,那麼由於我們每週會去向下探索,所以下一週探測時也可以及時調整正確。

d)冗餘Sync和心跳

在使用者的一些主動操作以及聯網狀態改變時,增加冗餘Sync和心跳,確保及時收到訊息。
  • 1、當用戶點亮螢幕的時候,做一次心跳。
  • 2、當微信切換到前臺時,做一次Sync。
  • 3、聯網時重建信令TCP,做一次Sync。

八 可能存在的風險及預防措施


DHCP租期因素:
  • 1、問題:根據目前的測試結果顯示,安卓不續約到期的IP Bug,會導致TCP連線在不確定的時間點失效,從而會導致一次心跳失敗。
  • 2、預防:統計後臺穩定期的心跳成功率,上報給後臺。後臺可以按地區分網路監控這個指標的波動,並且後臺可以根據不同的波動,動態調整某區域特定網路下可選的心跳區間。

9 附錄


1附錄A:NAT超時介紹


因為 IP v4 的 IP 量有限,運營商分配給手機終端的 IP 是運營商內網的 IP,手機要連線 Internet,就需要通過運營商的閘道器做一個網路地址轉換(Network Address Translation,NAT)。簡單的說運營商的閘道器需要維護一個外網 IP、埠到內網 IP、埠的對應關係,以確保內網的手機可以跟 Internet 的伺服器通訊。

移動端IM實踐:實現Android版微信的智慧心跳機制_QQ20160303-2.png 

大部分移動無線網路運營商都在鏈路一段時間沒有資料通訊時,會淘汰 NAT 表中的對應項,造成鏈路中斷。

下表列出一些已測試過的網路的NAT超時時間(更多資料由於測試條件所限沒有測到):
地區/網路NAT超時時間
中國移動3G和2G5分鐘
中國聯通2G5分鐘
中國電信3G大於28分鐘
美國3G大於28分鐘
臺灣3G大於28分鐘

長連線心跳間隔必須要小於NAT超時時間(aging-time),如果超過aging-time不做心跳,TCP長連線鏈路就會中斷,Server就無法傳送Push給手機,只能等到客戶端下次心跳失敗後,重建連線才能取到訊息。

2附錄B:安卓DHCP的租期(lease time)問題


目前測試發現安卓系統對DHCP的處理有Bug:

  • 2、未到租期的一半時間,安卓裝置重新向DHCP Server申請IP租用。從目前測試結果來看,這種現象恢復的比較快。
  • 3、移動2G/3G,聯通2G沒有抓到DHCP。
  • 4、美國3G下抓取24小時,沒有抓到DHCP。

全站即時通訊技術資料分類


[1] 網路程式設計基礎資料:
TCP/IP詳解 - 第11章·UDP:使用者資料報協議
TCP/IP詳解 - 第17章·TCP:傳輸控制協議
TCP/IP詳解 - 第18章·TCP連線的建立與終止
TCP/IP詳解 - 第21章·TCP的超時與重傳
理論經典:TCP協議的3次握手與4次揮手過程詳解
理論聯絡實際:Wireshark抓包分析TCP 3次握手、4次揮手過程
計算機網路通訊協議關係圖(中文珍藏版)
NAT詳解:基本原理、穿越技術(P2P打洞)、埠老化等
UDP中一個包的大小最大能多大?
Java新一代網路程式設計模型AIO原理及Linux系統AIO介紹
NIO框架入門(三):iOS與MINA2、Netty4的跨平臺UDP雙向通訊實戰
NIO框架入門(四):Android與MINA2、Netty4的跨平臺UDP雙向通訊實戰
>> 更多同類文章 ……

[2] 有關IM/推送的通訊格式、協議的選擇:
為什麼QQ用的是UDP協議而不是TCP協議?
移動端即時通訊協議選擇:UDP還是TCP?
如何選擇即時通訊應用的資料傳輸格式
強列建議將Protobuf作為你的即時通訊應用資料傳輸格式
移動端IM開發需要面對的技術問題(含通訊協議選擇)
簡述移動端IM開發的那些坑:架構設計、通訊協議和客戶端

相關推薦

適應心跳機制

原文連結:http://www.52im.net/thread-120-1-1.html本文由微信開發團隊人員編寫,轉自 WeMobileDev,感謝。一 引言在2013年11月中旬時,因為基礎元件組人手緊張,Leo安排我和春哥去廣州輪崗支援。剛到廣州的時候,Ray讓我和春哥

netty定義心跳機制

   在我的上一篇文章中已經介紹過了rts遊戲的基本架構,下面來看一下心跳協議的使用    在netty中重寫ChannelInboundHandlerAdapter的userEventTriggered方法可以實現心跳協議的檢測,寫起來也比較簡單,網上的demo很多,但是

高效 保活長連線:手把手教你實現 適應心跳保活機制

前言 當實現具備實時性需求時,我們一般會選擇長連線的通訊方式 而在實現長連線方式時,存在很多效能問題,如 長連線保活 今天,我將 手把手教大家實現自適應的心跳保活機制,從而能高效維持長連線 目錄 1. 長連線 介紹 1.1 簡

高效 實現長連線保活:手把手教你實現 適應心跳保活機制

以下內容轉載自http://blog.csdn.net/carson_ho/article/details/79522975前言當實現具備實時性需求時,我們一般會選擇長連線的通訊方式而在實現長連線方式時,存在很多效能問題,如 長連線保活今天,我將 手把手教大家實現自適應的心跳

適應註意力機制在Image Caption中的應用

bcd 情報 cpc gpl ice ive 放大 pcf contex 在碎片化閱讀充斥眼球的時代,越來越少的人會去關註每篇論文背後的探索和思考。 在這個欄目裏,你會快速 get 每篇精選論文的亮點和痛點,時刻緊跟 AI 前沿成果。 點擊本文底部的「閱讀原文」即刻

適應PC端網頁制作使用REM

一次 常見 上下左右 以及 body 效果 上下 boot ott 做一個PC端的網頁,設計圖是1920X1080的. 要在常見屏上顯示正常(比例正確可) 1280X720 1366X768 1440X900 1920X1080 使用了幾種辦法 1.內容在一屏內顯示的,

div實現適應高度的textarea,實現angular雙向綁定

amp 屬性 top 方式 androi android 可編輯 str == 相信不少同學模擬過騰訊的QQ做一個聊天應用,至少我是其中一個。 過程中我遇到的一個問題就是QQ輸入框,自適應高度,最高高度為3row。 如果你也像我一樣打算使用textarea,那麽很抱歉,你一

Jquery使容器適應瀏覽器窗口

cti -s meta 方法 jquer charset mar utf-8 ava 一、幾個關鍵點 1:當文檔大小改變時可以通過哪個事件來觸發? resize([Data], fn) 可傳入data供函數fn處理。 示

左右定寬中間適應布局

padding adding head idt class 適應 htm meta clas <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8">

css之兩欄布局左側固定右側高度適應

iscis pyo class cdh man db4 內容 tmx usb css兩欄布局之左側固定右側高度自適應先看這樣的html+css結構: .main { width: 900px; overflow:hidden; m

java適應響應式 企業網站源碼 SSM 生成靜態化 手機 平板 PC

java企業網站源碼 模版 有前後臺 freemaker springmvcssm java 企業網站源碼 前後臺都有 靜態模版引擎, 代碼生成器大大提高開發效率前臺: 支持兩套模版, 可以在後臺切換系統介紹:1.網站後臺采用主流的 SSM 框架 jsp JSTL,網站後臺采用freema

CSS完美實現iframe高度適應(支持跨域)

真的 高度 org lns nal aid .org bsp 方法 Iframe的強大功能偶就不多說了,它不但被開發人員經常運用,而且黑客們也常常使用它,總之用過的人知道它的強大之處,但是Iframe有個致命的“BUG”就是iframe的高度無法自動適應,這一點讓很多人都頭

左邊固定,右邊適應布局的兩種實現

定位 abs red logs light 正常 idt blue mar html結構: <body> <div class="left"></div> <div class="right"></div

0512日重點:淘寶的H5手機端適應解決方案:Flexible

自動獲取 手機端 issue 解決方案 target 解決 flex get bsp 參考文檔: https://github.com/amfe/lib-flexible https://github.com/amfe/article/issues/17 自我總結:F

如何通過 WebP 適應方案減少圖片資源大小

ont 圖片文件 display zip 副本 org 占比 會有 xhtml 前言 我們知道,理想的網頁應該在 1 秒內打開,而在頁面的整體大小中,圖片往往是所占比例最大的一部分(大約占到 60% 以上,更多了解請點擊),也可以參照如下圖所示。優化圖片不僅可以加快頁面顯示

Winfrom PictureBox 設置圖片適應

bitmap cnblogs oms system from mage blog style pre 初始狀態 1 Bitmap bm = new Bitmap(Image.FromStream(System.Net.WebRequest.Create(n

css實現適應正方形的方法

固定 如果 spa size 一個 idt width 正方 pad 頁面布局中,我們經常需要用百分比來實現寬度自適應,但是如果這時候高度要跟寬度呈固定比例變化,該怎麽辦呢? 很簡單,我們可以利用元素的padding或margin的百分比值是參照寬度的這一特性來實現, 即如

移動端用rem使字體適應

對比 16px size 設置 自適應 使用 pre 感覺 字體大小  rem是css3引入的新的單位,與px和em相對比,我感覺rem更加便利,尤其是對移動端的字體自適應布局。  rem是根據HTML的字體大小進行設置的。  而HTML的基本字體大小是16px,所以可

textarea 高度適應

100% important har .proto paste lin arr property value 一、$(‘textarea‘).keyup(function () { $(this).height(this.scrollHeight); });效果一般

textarea高度適應

area 方案 any 復用 his input extra function csdn textarea高度自適應 有時候寫表單的時候,會有一個 備註框textarea。因為textarea不支持自適應高度,就是定好高度或者是行數之後,超出部分就會顯示滾動條,看起來不