得物自研移動端弱網診斷工具的技術實踐分享
一、引言
隨着得物用戶規模和業務複雜度不斷提升,端上網絡體驗優化已逐步進入深水區。爲了更好地保障處於弱網狀態下得物 App 用戶的使用體驗,我們在已有的網絡體驗大盤、網絡診斷工具的基礎上研發了弱網診斷能力。該工具能夠高效實時診斷用戶真實網絡環境,同時給出精確網絡質量分級,爲後續 App 各業務場景進行鍼對性優化做好基礎建設保障。
本文將基於得物自研的移動端弱網診斷工具的開發過程,儘可能全面地爲你總結和分享它的具體技術實踐,希望帶給你啓發。
二、本文目錄
1) 引言
2) 網絡性能概念
3) 整體架構
4) 採集層實現 1:HttpRTT 採集
-
4.1 概述
-
4.2 採集樣本過濾
5) 採集層實現 2:吞吐量(throughput)採集
-
5.1 概述
-
5.2 時間窗口
-
5.3 數據量
-
5.4 髒數據過濾
6) 策略層實現
-
6.1 中位數
-
6.2 時間權重
-
6.3 信號強度權重
-
6.4 加權中位數
-
6.5 計算與緩存
7) 接口層實現
8) 閾值定義
9) 性能指標
-
9.1 HttpRTT 數值計算
-
9.2 吞吐量(throughput)數值
-
9.3 準確性判定
-
9.4 線上數據
-
9.5 不準確性來源
10) 應用場景
11) 本文小結
12) 參考資料
13) 得物技術團隊的其它文章
三、網絡性能概念
一些網絡性能指標:
-
1) 速率:指傳送數據的速率。速率是計算機網絡中最重要的性能指標,單位是 b/s(比特每秒,也寫作 bps ,即 bit per second)。速率較高時可寫作 kbps,mbps。
-
2) 帶寬:帶寬用來表示網絡的通信線路傳送數據的能力,表示在單位時間內從網絡中的某一點到另一點所能通過的 “最高速率”。
-
3) 吞吐量(throughput):表示在單位時間內通過某網絡的數據量。吞吐量常用於對網絡的一種測量。吞吐量受網絡帶寬或者速率限制。例如,對於一個 100Mb/s 的網絡,其額定速率是 100Mb/s,那麼該數值是此網絡的吞吐量的上限,其吞吐量可能只有 70Mb/s。
-
4) 時延:指數據從網絡上的一端傳輸到另一端所需要的時間。
-
5) 往返時間 RTT(Round-Trip Time):表示從發送方發送數據開始,到發送方收到接收方的確認,總共經歷的時間。
-
6) HttpRTT:指從客戶端請求的第一個字節開始發送到收到第一個數據包響應的時間差。這個時間包含 3 個部分,客戶端發送數據到服務器耗時、服務器處理耗時、服務器響應數據到客戶端耗時。
弱網診斷觀察的指標(弱網診斷根據 HttpRTT 和吞吐量來觀察用戶網絡環境):
-
1)HttpRTT:在不考慮服務器處理耗時的情況下,能夠體現用戶請求被處理的真實時延。
-
2)吞吐量(throughput):用戶的額定速率能被系統提供的 API 獲取到,然而其僅能表示設備能夠提供的最大速率(一般很大),卻不是真實速率,而測量真實的吞吐量更能體現出用戶當前真實網絡環境。
四、整體架構
本次實現的是被動弱網診斷,也就是不主動發起探測請求,被動採集 App 內的全部網絡請求,再根據一定在策略計算出用戶網絡環境。
相對於主動探測,被動探測不會浪費用戶資源。
尤其是在吞吐量計算方面,主動探測不僅會消耗用戶流量,還可能會對正在進行中的用戶網絡請求產生影響。而且當用戶網絡環境不佳時,負向影響更加嚴重。
以下爲被動網絡診斷的整體架構圖:
五、採集層實現 1:HttpRTT 採集
5.1 概述
HttpRTT 的採集比較簡單,各端根據自身 Http 協議棧的實現獲取到從寫入 requestHeader 開始,到收取 responseHeader 的時間差即可。
對於 Android:我們通過 OkHttp 完成 Http 請求,通過向 OkHttp 註冊網絡監聽即可實現。
需要說明的是:在不修改源碼的情況下,Android 無法獲取到收到第一個響應數據包的時間,只能監聽到 Header 讀取完成,這會有些許誤差,但實測下來可以忽略。
對於其他客戶端內通過自行實現 Http 協議棧發起的網絡請求(如 PCDN),我們通過向其註冊特定的監聽回調,也能獲取到 HttpRTT。
5.2 採集樣本過濾
HttpRTT 包含了服務器處理時間,而當服務器處理時間過長或過低時對其他普遍意義上的 Http 請求參考價值相對較低。
因此我們需要排除這些數據:
-
_1)_localhost:如果向 localHost 發起請求,且響應的僅是緩存的數據,那麼其 HttpRTT 時延明顯接近於 0;
-
_2)_PUT 請求:由於 PUT 請求傳輸的數據量一般較大,其 HttpRTT 明顯高於其他;
-
_3)_其他明顯偏離的數據。
六、採集層實現 2:吞吐量(throughput)採集
6.1 概述
throughput(bit/s , bps) = 單位時間內通過的數據量 (bit) / 單位時間 (s)
吞吐量的採集相對要複雜得多,吞吐量採集目的是獲取用戶所能使用的最大的數據率(或帶寬),因而其需要在設備上恰好有大量數據正在傳輸時採集。
對於主動探測來說,在無其他請求干擾的情況下,主動發起一個大數據量 CDN 下載請求即可快速測量出吞吐量。而被動探測則需要想辦法預測或檢測到大量數據傳輸的時刻,並適時計算吞吐量。
6.2 時間窗口
怎樣選取計算吞吐量的時間窗口是計算吞吐量準確性的關鍵。
這個窗口要恰好在大量數據正在傳輸時,不能早也不能晚:
-
1) 如果提前開啓了時間窗口,那麼同樣的大小的數據通過,由於分母增大會導致計算出的數值偏低;
-
2) 如果數據傳輸完成後,稍晚關閉時間窗口,那麼同樣會由於分母增大而導致計算出的數值偏低。
我們知道 Http 請求或多或少會有上行 / 下行數據,但由於服務器處理耗時長短的不確定性(不能算在分母裏),單個 Http 請求測速時並不可靠。
而多個 Http 正在併發請求進行中的時候,其請求的流量會疊加,單個請求的服務器耗時會被其他 Http 請求覆蓋,此時採集吞吐量會是個好的選擇。因此,我們可以在監聽到 Http 併發請求數量達到 5 個以上時採集吞吐量。
時間串口的選擇(忽略建連耗時):
可以看出,當併發較多時,服務器耗時會被覆蓋,每個時間窗口內存在約 4 個 Http 請求的響應數據。
我們始終監聽 App 內的全部 Http 請求,當監控到有 5 個及以上的網絡請求尚未完成時,也就是 Http 併發 5 個以上,開啓時間窗口;當時間窗口已開啓且任意一個請求結束時,我們結束當前時間窗口。
需要注意的是:當我們結束一個時間窗口的時候,需要立刻檢測當前併發是否 5 個以上,而不是等到新的請求到來時,這樣能避免類似上圖的採樣機會被浪費掉,而採樣成功的樣本數越多,越有利於最終結論的準確性(後面策略層會講原因)。
_可行性:_我們的 App 內能滿足 5 個併發以上嗎?
當然可以。通過觀察線下測試和線上數據分析,我們 App 內的併發數能夠滿足吞吐量採集的必要條件。舉個例子,進入商詳一次的併發量就能滿足。
用戶 A 啓動 90 秒內 Http 併發數量(線上數據):
6.3 數據量
分母(單位時間)的問題解決了,分子(單位時間內通過的數據量)如何取值呢?
思路是:
-
1) 思路 1:當前時間窗口內並行的 Http 通過的 Reponse 數據量;
-
2) 思路 2:設備內所傳輸的數據量;
-
3) 思路 3:當前網卡傳輸的數據量。
先說思路 1:這個實現上需要我們在時間窗口開始時記錄全部 Http 請求已傳輸的字節數,時間窗口關閉時再記錄一次,然後把當前並行的 Http 請求時間窗口內的數據量全部累加起來。這意爲着我們要時刻監控每一個 Http 請求中每個字節的讀取,成本太高了。另一方面,如果有其他非 Http 請求(或者我們 App 之外的請求)也在進行,我們僅測算 App 內 Http 請求的吞吐量顯然是偏低的。因此,思路 1 不合適。
再說思路 2:相對合適。我們要測算的就是設備的吞吐量。因爲即使是 App 外的流量,其也會有結束的時候,總能爲我們所用(除非用戶對我們 App 單獨做帶寬限制)。
相對於獲取設備內的全部流量,獲取網卡的流量則更爲合適:
-
1) 原因 1:部分系統已經支持 WIFI 與蜂窩並行請求,如果當前使用的是 WIFI,將 App 外的蜂窩流量測算進去會導致偏差。
-
2) 原因 2:網絡切換時,處於舊網絡上的請求不會立即釋放,而新的請求會發生在新的網絡上,此時設備內的通過的流量是多網卡的累積。
需要注意的是系統 API 返回的是字節數(byte),而我們計算的是 bit,因此計算吞吐量時需要進行換算。
6.4 髒數據過濾
前面講到 “併發 5 個時,每個時間窗口內可以採集到約 4 個 Http 請求的響應數據”,然而運氣並不會始終這樣好。
窗口掛起:
如上圖所示:時間窗口 1 內僅兩個有效的 response,時間窗口 2 內僅一個有效的 response,其計算出的吞吐量必然是偏低的。因此,髒數據過濾就顯得十分重要。
1)小數據量過濾:
時間窗口內通過的流量小於 32KB 時,不會產生準確的速率,我們直接忽略這次採樣。要知道,一個圖片的數據量都可能會超過 32KB。
2)低利用率過濾:
低利用率是指由於數據需求較小,導致當前速率遠未達到最大吞吐率的情況。如上圖時間窗口 1,對於一個未被充分利用的網絡,我至少希望一個 HttpRTT 的時間內接收到的數量大於 15KB。
// 窗口是否掛起
fun isHangingWindow(bitsRx: Long, duration: Long): Boolean {
val kCwndSizeBits = 10 * 1.5 * 1000 * 8
val multiplier = 1
val httpRTT = ??? //由Http RTT模塊計算
val bitsReceivedOverOneHttpRtt = bitsRx * httpRTT / duration
return bitsReceivedOverOneHttpRtt < kCwndSizeBits * multiplier
}
爲什麼是 15KB ?如果 TCP 連接剛剛建立,由於 Linux 系統的默認設置,客戶端能夠同時發送 10 個數據段,每個數據段時 1460 字節,合計也就是 15KB。
八、參考文獻
[1] 通俗易懂 - 深入理解 TCP 協議(下):RTT、滑動窗口、擁塞處理
http://www.52im.net/thread-515-1-1.html
[2] 現代移動端網絡短連接的優化手段總結:請求速度、弱網適應、安全保障
http://www.52im.net/forum.php?mod=viewthread&tid=1413
[3] 移動端 IM 開發者必讀 (一):通俗易懂,理解移動網絡的“弱” 和“慢”
http://www.52im.net/thread-1587-1-1.html
[4] 全面瞭解移動端 DNS 域名劫持等雜症:原理、根源、HttpDNS 解決方案等
http://www.52im.net/thread-2121-1-1.html
[5] 美圖 App 的移動端 DNS 優化實踐:HTTPS 請求耗時減小近半
http://www.52im.net/thread-2172-1-1.html
[6] 百度 APP 移動端網絡深度優化實踐分享 (三):移動端弱網優化篇
http://www.52im.net/thread-2678-1-1.html
[7] 愛奇藝移動端網絡優化實踐分享:網絡請求成功率優化篇
http://www.52im.net/thread-2981-1-1.html
[8] 美團點評的移動端網絡優化實踐:大幅提升連接成功率、速度等
http://www.52im.net/thread-3015-1-1.html
[9] IM 開發者的零基礎通信技術入門 (十二):上網卡頓?網絡掉線?一文即懂!
http://www.52im.net/thread-2406-1-1.html
[10] 淘寶移動端統一網絡庫的架構演進和弱網優化技術實踐
http://www.52im.net/thread-4470-1-1.html
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/kBSuqXAaWNNDZCcoiDADBA