弱網下移動端網絡連接處理策略
一、背景
如何度量和模擬“弱網絡”對移動APP的開發有著重大的意義,比如:節約測試成本、易于問題重現、加快產品上線等。
一般的方法是使用“丟包率”和“網絡延時”來定義和衡量“弱網絡”。
二、手機接入服務器的流程
要講這個問題,首先要來了解下手機接入服務器的流程。
- 首先,手機要通過無線網絡協議,從基站獲得無線鏈路分配,才能跟網絡進行通訊。
- 無線網絡基站、基站控制器這方面,會給手機進行信號的分配,已完成手機連接和交互。
- 獲得無線鏈路后,會進行網絡附著、加密、鑒權,核心網絡會檢查你是不是可以連接在這個網絡上,是否開通套餐,是不是漫游等。核心網絡有SGSN和GGSN,在這一步完成無線網絡協議和有線以太網的協議轉換。
- 再下一步,核心網絡會給你進行APN選擇、IP分配、啟動計費。
- 再往下面,才是傳統網絡的步驟:DNS查詢、響應,建立TCP鏈接,HTTP GET,RTTP RESPONSE 200 OK,HTTP RESPONSE DATA,LAST HTTP RESPONSE DATA,開始UI展現。
這是手機通過無線網絡接入服務器的全過程。整個過程當中有幾個困擾開發者的問題:
無線網絡是怎么給手機分配到無線鏈路的?
核心網絡有接入點(APN),這里的CMNET和CMWAP有什么區別,僅僅是協議不同嗎嗎?數據轉發又有什么區別?一個數據包在不同網絡上傳輸有不同嗎?
用戶怎么最快的找到正確的服務器?內容怎么快速有效的加載,在第一時間顯示出來?
這幾個問題的重點在于其中的幾個連接點:
- 無線鏈路分配。這是一個物理實連接。
- IP層鏈接。這是一個邏輯虛連接。
- TCP層鏈接。這是一個邏輯虛連接。
- HTTP層鏈接。這是一個邏輯虛連接。
- 用戶在線。這是一個邏輯虛連接。
3.2 一秒鐘法則
根據以上情況,就形成無線網絡的一大特點:秒級狀態管理,秒級狀態轉換。這兩個操作都在幾百ms到幾秒之間進行,對于維持連接來說時間太短,對于從無連接到有連接的轉換來說時間又太長。
相比之下,有線網絡的狀態管理如ip分配、tcp連接釋放,都是分鐘級,而狀態轉換則是毫秒級。
這些通訊機制,同時加上無線網絡的高延遲、高丟包。如何保證移動互聯網的產品提供穩定的、可預期的服務質量,成為非常大的挑戰:
2G網絡上無線部分數據傳輸的延遲有幾百ms,4G網絡上無線部分傳輸延遲減少到幾十ms,核心網狀態轉換、協議轉換30~100ms,IP骨干網上的延遲又跟物理距離以及運營商互聯互通質量有關,跨運營商50-400ms,同運營商5-80ms,這個還要取決于網絡擁塞的情況。
無線網絡誤碼率比有線高兩個數量級,在不同時間段的波動也非常巨大。
怎么基于移動網絡的特性去優化服務?
這就是我們總結的一秒鐘法則:在一秒內要完成的規定動作。
- 2g網絡:1秒內完成dns查詢、和后臺服務器建立連接
- 3g網絡:1秒內完成首字顯示(首字時間)
- wifi網絡:1秒內完成首屏顯示(首屏時間)
- 這些指標需要在終端度量,必須跟用戶體驗相關:首字時間、首屏時間都必須是用戶可以直觀感受到的。
四、優化思路
4.1 服務保證原則
從以上分析可知,如何保證移動互聯網的產品提供穩定的、可預期的服務質量,具有非常大的挑戰。以下幾點原則可能會有幫助:
- 接口設計優化,接口的優化理論上不屬于APP弱網絡的優化,但是這個的API性能的問題,確實在網絡條件不好的情況下才暴露無遺。大家都在談論服務器的好壞,設備的性能高低,其實,對于一個良好的Server來說,絕大部分拖延請求速度的地方都是在IO上。包括,磁盤讀寫的IO,SQL查詢的IO等等。常用的優化點:慢查詢監控 、多次查詢優化、常用接口cache等。
- 圖片相關策略。
- 使用更快的圖片格式,嚴格說也不算弱網下的優化,但一個更快的圖片格式真的很重要!這里建議采用WebP格式。(WebP格式,谷歌(google)開發的一種旨在加快圖片加載速度的圖片格式。圖片壓縮體積大約只有JPEG的2/3,并能節省大量的服務器帶寬資源和數據空間。但WebP是一種有損壓縮。相較編碼JPEG文件,編碼同樣質量的WebP文件需要占用更多的計算資源。)
- 不同網絡的不同圖片下發。如(對于原圖是600X480的圖片):2/3G使用低清晰度圖片——>下發300X240,精度為80的圖片、4G普通清晰度圖片——>下發600X480,精度為80的圖片、WiFi高清晰度圖片(最好根據網速來判斷,wifi也有慢的)——>下發600X480,精度為100的圖片。
- 斷線重連。這可能是最重的一個特性,因為在無線網絡中有太多的原因導致數據連接中斷了。這里可以使用CDN。(CDN 是構建在數據網絡上的一種分布式的內容分發網。 CDN 的作用是采用流媒體服務器集群技術,克服單機系統輸出帶寬及并發能力不足的缺點,可極大提升系統支持的并發流數目,減少或避免單點失效帶來的不良影響。)
- 由于創建連接是一個非常昂貴的操作,所以應盡量減少數據連接的創建次數,且在一次請求中應盡量以批量的方式執行任務。如果多次發送小數據包,應該盡量保證在2秒以內發送出去。在短時間內訪問不同服務器時,盡可能地復用無線連接。
- 優化DNS查詢。應盡量減少DNS查詢、避免域名劫持、DNS污染,同時把用戶調度到“最優接入點”。
- 減小數據包大小和優化包量。通過壓縮、精簡包頭、消息合并等方式,來減小數據包大小和包量。
- 控制數據包大小不超過1500,避免分片。包括邏輯鏈路控制(Logic Link Control)分片、GGSN分片,以及IP分片。其中,當數據包大小超出GGSN所允許的最大大小時,GGSN的處理方式有以下三種:分片、丟棄和拒絕。
- 優化TCP socket參數,包括:是否關閉快速回收、初始RTO、初始擁塞窗口、socket緩存大小、Delay-ACK、Selective-ACK、TCP_CORK、擁塞算法(westwood/TLP/cubic)等。做這件事情的意義在于:由于2G/3G/4G/WIFI/公司內網等接入網絡的QoS差異很大,所以不同網絡下為了取得較好的服務質量,上述參數的取值差異可能會很大。
- 優化ACK包。在弱網絡的情況下,TCP協議中的ACK包是非常昂貴的,延時甚至能夠達到秒級別,而TCP協議的擁塞控制、快速重傳、快速恢復等特性都非常依賴接收端反饋的ACK包。可想而知,如果發送端接收到的ACK包延時太長,會嚴重影響TCP協議的效率。但是如果發送ACK太多又會占用寶貴過多的無線資源。在移動網絡下通信,“在可靠的連接上,如何在減少ACK包的情況下,降低數據包的延時”是研究的熱點。基本的思想:平衡冗余包和ACK包個數,達到降低延時,提高吞吐量的目的。例如SGSN和GGSN之間的通信實現:二者之間通過UDP協議通信,發送者在無新的數據包的情況下,每隔一定的時間重試已發送的包,達到最大重試次數后,則丟棄該包。
- TCP的擁塞控制算法是以“丟包意味著網絡出現擁塞”為假設設計的,很明顯這個假設在無線網絡環境下是不合適的。但是在無線網絡環境下,在設計可靠UDP協議時是否能夠完全丟棄擁塞控制呢?這里有其它的文章中提出了幾種在無線網絡環境下的TCP友好的擁塞控制算法,有興趣可以自行查閱。
- 靈活使用長連接/短連接,支持不同協議(TCP/UDP, http、二進制協議等),支持不同端口等。
- 讓用戶覺得快。到這里已經不能算是技術層面的方法了,屬于一種心理層面的博弈,一種改善用戶體驗的方式。比如:
- 不從0開始的進度條。不管網頁的加載進度如何,不管網絡條件如何,加載進度始終是從50%起,并且停留在大約98%進度左右的地方。
- 先顯示文字在加載圖片。同樣是在Webview之中,圖片或者多媒體的加載速度肯定是遠遠慢過文字的加載速度的。由于不同的webview顯示和渲染效果不同,我們可以先讓webview先顯示文字,在顯示圖片。給用戶一種可以先預覽整個網頁概況的感覺。
4.2 接入調度優化
接入調度優化首先要考慮的是減少DNS的影響。移動網絡的DNS有如下特點:
- 骨干網無法識別移動用戶在哪個城市,東西南北各個地方的調度沒有充分調用。目前有一部分全國范圍的DNS承載了超過40%的全網用戶
- 很多山寨機的終端local dns設置是錯誤的
- 另外還有一些有線網絡也一樣會遇到的問題,如終端DNS解析濫用、域名劫持、DNS污染、老化、脆弱等。不過對于這些問題,桌面的自愈性會比較好,而在手機上則比較難以解決。
對于DNS的問題,有兩條主要的解決思路:
- 減少DNS的請求、查詢、更新,也就是做DNS緩存
- 在終端配置server list,直接訪問IP,不用DNS
但僅僅這么做還不夠,因為用戶可能來自國內外不同的運營商,還需要進一步優化調度策略:
- DNS緩存需要多建立接入點,用不同域名區分
- IP列表需要更新以適應不同網絡情況,要做到主動調度。好比最早我們只服務好移動用戶就行,保證移動用戶的接入質量優先,因為絕大多數用戶集中在移動;現在國內有三個運營商,用戶分布的比例在慢慢接近,要區分清楚;智能手機會用wifi,接入的是電信、聯通還是哪個運營商,不知道,所以你不可能預先設置場景再if then,必須通過后臺調度能力來解決。
再進一步優化,就產生一種融合的方式:
- 先做域名解析,客戶端直接連接解析的IP,可以用http協議,也可以用tcp socket
- 多端口、多協議組合:不同協議有不同的限制,有些只能http,有些只能tcp socket,各種環境都要適應,客戶端不能只支持一種協議
- 終端測速:接入點越來越多,接入哪個合適,要選擇,可以通過終端測速來選擇最快的。你當然可以每一次新建連接都做測速,但是這樣建立連接時間可能會很長;我們可以給用戶先建立連接后,在后臺根據長期速度監控、當前測速的結果,來做動態調度。也就是說,第一次連接可能不是最優,連接建立后動態測速,再轉移到最快接入點。更進一步就是建立網絡profile,終端學習的思路。
關于測速采樣的粒度,移動互聯網取IP段是沒用的,比較好的粒度是到網元級別,比如廣東有20多個wap網關,每一個網關的情況都不一樣,這就是一個比較合適的粒度。
最后強調一個所有的接入調度原則:不要把調度邏輯寫死在客戶端,一定要由后臺完成。
4.3 協議優化
協議參數優化這塊就簡單列一下,是長期運營過程中總結的一些經驗,在啟動移動互聯網服務時作為運營的規范,可以少走很多彎路:
- 關閉TCP快速回收
- Init RTO不低于3秒
- 初始擁塞控制窗口不小于10。因為大部分頁面在10kB以下,很多請求在慢啟動階段已經結束,改為10可以降低小頁面資源傳輸時延。內容越大,這個選項的效果就比較不明顯。
- Socket buffer > 64k
- TCP滑動窗口可變
- 控制發包大小在1400字節以下,避免分片
協議優化的原則總結下來是這么幾條:
- 連接重用
- 并發連接控制
- 超時控制
- 包頭精簡
- 內容壓縮
- 選擇更高效率的協議。無論是TCP、HTTP、UDP、長連接、GZIP、SPDY、WUP還是WebP,每一種協議、方案都有其道理,沒有最優,只有是否適合你的產品和服務特點,需要大家在運營過程驗證和取舍。
4.4 WAP接入點優化
關于WAP接入點優化,可能有些人會說,我們的App是高端大氣上檔次的應用,是不是就不用做WAP優化?實際上我們的統計顯示,目前有5%-20%的用戶選擇的接入點是*WAP(CMWAP、3GWAP、CTWAP),這甚至包括一些iPhone終端。實際上,WAP網關本質是個代理,不完全是落后的東西,隨著技術的進步也在演進,以后在組網架構中可能有綜合網關、內容計費網關來取代目前的WAP網關,所以建議也要一并考慮。以下是做WAP優化需要注意的一些問題:
- 資費提醒頁面
- 302跳轉處理
- X-Online-Host使用與處理
- 包大小限制
- 劫持與緩存
- 正確獲取資源包大小
4.5 業務邏輯優化
1、簡化邏輯:交互繁瑣的內容盡量用標識更新。舉一個例子,我們在老版的手機QQ上做過一個測試:假如我有100個好友,用手機QQ完成登陸,完成好友列表更新一遍,需要3.5分鐘。這肯定是不合理的。建議用信令狀態來通知是否需要更新,同時合理利用緩存。在比如玩游戲,好友給你送了很多星星,是讓用戶一次一次點還是批量點?從優化的角度肯定是批量點,從用戶體驗的角度這也更加舒服。
另一方面,延長域名圖標的緩存時間也可以有效地優化訪問次數。我們把手機騰訊網圖標的緩存時長從120分鐘延長到2天后,訪問次數優化了差不多35%。
2、柔性可用:這個意思就是在網絡質量好的時候給高清大圖,不好的時候先給用戶看小圖,點一下再拉取原圖。舉一個極端的例子,比如萬一地震了,基站毀掉20%,用戶要給家人報平安,這時候產品上就必須優化,比如只發送文字,合理降3,低網絡消耗。另外在響應很慢的時候,需要給用戶一些合理的頁面提示,比如提示用戶再過5秒會發送,所以你不要一直刷屏,這也可以減少訪問對后臺服務、對網絡的沖擊。
五 實戰演示
5.1 一個最優調度設計示例
上面說了那么多,這里就給出一個實例幫助大家更直觀的理解。
這里給出一個DNS系統設計來實現最優調度。其拓撲結構如下:
TGCP SDK的職責:
- 用HTTP的Get/Post方法從DNSvr獲服務器和DNSvr本身的最優接入點列表。Get/Post方法的查詢參數包括uin/openid、客戶端版本號、IP列表的MD5(注意IP順序)、域名列表、VIP、ServiceID等。
- 緩存訪問服務器和DNSvr的IP列表,以及其它元數據(比如IP列表等),且以APN為主鍵。
- 滿足一定的條件下,要主動更新緩存的IP列表,例如緩存過期。
Tconnd的職責:
- 路由查詢請求給活動的DNSvr;
DNSvr的職責:
- 根據靜態和動態策略來決定客戶端的“最優接入點”。靜態策略:根據uin/openid、客戶端版本號或者強制規則來決定IP列表;動態策略:燈塔根據測速數據動態決定用戶的服務器接入點。
- 支持以手動或自動的方式拉黑某些IP。自動方式:由服務器的接入tconnd向DNSvr上報其是否存活(需要向多個點上報,包括用公網IP上報),如果在一定時間內沒有接收到上報或者上報消息中明確所有的邏輯服務器已經掛掉,則自動拉黑相應的IP。如果業務恢復,則自動激活相應的IP。如果項目組接入TGW,對于某個IP和端口是否可用,則需要考慮進程與VIP的映射關系。
- 在tcaplus中緩存燈塔的計算結果。此時要求DNSvr能夠根據客戶端IP判斷所屬的國家、省份、運營商和網關(可以通過訪問MIG的IP庫實現)。如果緩存了燈塔的計算結果,當緩存超時后,要重新從燈塔拉取相應數據。
燈塔的職責:
- 根據客戶端IP和服務器接入點IP,返回最優的接入點列表,包括IP的排序,以及客戶端接入的國家、省份、運營商、APN和網關。
Tcaplus的職責:
- 保存接入的IP列表和端口、靜態策略,或緩存燈塔的計算結果;
主要的流程:
客戶端批量解析域名流程
- TGCP以APN和域名列表為關鍵字查詢緩存,如果存在且沒有過期,則直接把IP返回給用戶。如果指定強制解析域名列表,則跳過此步驟;
- TGCP用預配置或緩存的IP向DNSvr發起查詢請求,如果成功返回結果,則執行步驟3,否則,重試IP列表中的其它IP,如果都失敗,則用域名訪問DNSvr。注意:如果是結果格式不正確,則使用上次的IP重試,不要更換IP重試。
- DNSvr比較客戶端IP列表和當前最新的IP列表的MD5,如果相等,則告訴客戶端不需要更新本地緩存。否則,TGCP把接入服務器和DNSvr的IP列表寫入本地。注意:在訪問服務器時,這些IP的優先級要高于靜態配置在客戶端的IP。
客戶端使用域名訪問服務器流程
- 如果本地存在有效的IP(即存在對應APN的IP列表,且沒有失效),則使用IP訪問服務器。
- 否則,發起“客戶端批量解析域名流程”后,再訪問服務器。
服務器接入tconnd主動上報狀態流程:
- Tconnd周期性向DNSvr上報心跳消息,其中包含本接入點是否可用的信息。
- DNSvr在一定的時間內沒有收到心跳消息或者相應的接入點不可用,則把相應的IP和端口拉黑,黑掉的IP不在下發給客戶端。
注意:實際部署的時候,接入的Tconnd要向多個DNSvr接入tconnd上報。
向客戶端主動push接入點列表的流程
- 當TGCP連接到服務器接入的Tconnd時,Tconnd要向DNSvr發起請求,以校驗當前接入IP的質量和時效性。如果IP列表發生變化,Tconnd要把最新的IP列表下發給客戶端緩存起來。
- 當TGCP下次訪問服務器時,則使用最新的IP列表。
客戶端訪問DNSvr失敗的流程
- 如果訪問DNSvr失敗(包括IP+域名),如果配置了本地IP,則直接用IP訪問服務器,否則用域名訪問。
優化傳輸層協議設計
在原有tconnd支持的可靠UDP的基礎之上,添加以下邏輯:
- 數據壓縮;
- 數據加密;
- 合并多個數據包;
- 支持流式數據傳輸,便于控制每個UDP包的大小,也便于數據加密和壓縮;
- 可選地支持改進的擁塞控制算法;
- 即使沒有接收到ACK包,也需要主動重試以發送的數據包;
5.2 Hybird開發下的一些優化
要處理在弱網絡下的加載速度,那么我們要先確定一下我們的整個APP在哪個地方加載的速度如何,最長的加載路徑在哪里,我們從而才有針對性的進行優化與修改。
5.2.1 WebView
如果是對是APP中內嵌的webview網頁,針對網頁體驗優化已經由來已久了。我們可以使用Chrome的開發者模式,調整到Network模式下,將網絡條件設置為3G去請求網頁,那么我們就能夠看出來一個網頁加載的速度主要都耗費在哪個地方,如下圖所示:
當然,html的加速方式有很多種
- 使用gulpgrunt進行打包壓縮:jscss資源壓縮,CSS Sprites合并等。
- 使用font-awesome替換圖片:字體可以很好的兼容,無限放大,常用的圖片都有