1. 程式人生 > >Android網路效能監控方案

Android網路效能監控方案

阿里雲 雲原生應用研發平臺EMAS 劉寶文(木睿)

背景

移動網際網路時代,移動端極大部分業務都需要通過App和Server之間的資料互動來實現,所以大部分App提供的業務功能都需要使用網路請求。如果因為網路請求慢或者請求失敗,導致使用者無法順暢的使用業務功能,會對使用者體驗造成極大影響。 

此外,EMAS對外提供的APM之前並不包括網路監控功能,而網路效能監控作為移動端效能監控的重要組成部分,我們急需補全這部分能力來完善APM的產品功能,進一步滿足客戶的需求。

 “阿里巴巴應用研發平臺 EMAS 是國內領先的雲原生應用研發平臺(移動App、H5應用、小程式、Web應用等),基於廣泛的雲原生技術(Backend as a Service、Serverless、DevOps、低程式碼等),致力於為企業、開發者提供一站式的應用研發管理服務,涵蓋開發、測試、運維、運營等應用全生命週期。”

問題與挑戰

網路效能監控在端上主要包括資料採集和資料上報。我們希望能儘可能採集有用的資訊來幫助客戶發現、定位和解決網路效能問題。我們面臨如下問題和挑戰:

  • 首先要解決的是網路請求過程中,哪些階段會影響請求效能,如果發現網路效能有問題,需要採集哪些資料來幫助使用者去定位和解決問題。
  • android上主流的網路框架有okhttp2、okhttp3、okhttp4、volley、retrofit、httpclient和系統提供的httpurlconnection等,在我們不確定客戶使用哪個網路庫的哪個版本的情況下,如何儘量採集有用的資訊。
  • 網路請求各個階段的資料採集都是離散的,如何保證單個請求各個離散的監控資料能夠串聯起來,不和其他請求的監控資料混在一起。
  • 由於弱網環境下的網路請求日誌往往更有價值,需要儘可能將異常的網路請求日誌資料上報到服務端。
  • 併發網路請求時,需要確保在日誌上傳時儘量不影響客戶正常業務。

 

實現方案

網路效能監控在端上的具體實現主要包含兩大模組:

  • 資料採集
  • 資料上報

其中資料採集是整個SDK框架的核心。

整體架構概覽:

 

 

接入層:

網路監控屬於高可用產品的一部分,採用高可用統一接入的方式接入。

外掛層:

高可用目前框架是通過外掛式的方式整合各個業務,實現networkmonitor plugin整合到APM中,補充APM中網路監控部分。

邏輯層:

主要負責採集控制、資料管理、快取管理和資料上報。

攔截器層:

整個網路監控的核心。為了採集更多的資訊,我們選擇使用位元組碼注入技術來實現網路請求監控功能。對OkHttp、HttpClient和HttpUrlConnection,分別實現Interceptor去採集不同網路庫中網路請求各個階段的資料,並在請求結束時完成採集進行上報。此外,通過自定義gradle plugin的方式,為各個網路庫實現Injector和開關,控制在應用構建階段將Interceptor中各個採集的方法注入到對應網路庫位元組碼的埋點位置,從而實現在執行時網路請求各個階段採集需要的資料。

資料採集

採集哪些資料

首先需要確定採集的資料範圍來幫助我們及時發現網路請求的效能和異常等情況,另一方面也需要有額外的資料來輔助排查問題。所以我們採集的資料主要包括四個部分:

  • 基礎資料。
  • 效能資料。
  • 異常資訊。
  • 事件序列資料。
基礎資料

 

  • 請求url:對請求做聚合運算。
  • 目標IP地址:對於多出口IP的客戶,支援IP地址維度的資料分析。
  • dns解析結果:請求url的域名解析ip列表,用於分析是否存在域名劫持的問題。
  • http code:根據http code確定請求狀態。
  • 上行流量:包括整個請求上行header和body的總的流量,包含重試和重定向的上行流量。用於監控上行流量開銷。
  • 下行流量:包括整個請求下行header和body的總的流量,包含重試和重定向的下行流量。用於監控下行流量開銷。
  • 網路庫型別及版本:對於客戶更換網路庫或者升級網路庫版本的情況,可以提供前後的網路資料的差異。
效能資料

效能資料主要是採集整個網路請求中各個階段的耗時情況來定位慢請求發生的階段。下圖列舉了http請求可能出現的各個階段。

 

 

所以效能資料部分需要採集下述各個階段的耗時資料:

 

  • 整個網路請求耗時
    • dns耗時
    • 建連耗時
      • TLS建連耗時
    • 資料上行耗時
      • header上行耗時
      • body上行耗時
    • 資料下行耗時
      • header下行耗時
      • body下行耗時

 異常資訊

異常資訊主要是收集網路請求各階段出現異常時的異常棧的資訊。比如常見的java.net.UnknownHostException、java.net.SocketTimeoutException等。

事件序列資料

事件序列資料主要是收集網路請求各階段的監控事件的資訊,另外對於特定網路庫的一些特殊的事件的監控,比如okhttp的連線複用、自動重定向和失敗重試等對網路耗時有影響的機制。最後將這些事件按時間順序排列。

 

比如在okhttp上dns被劫持的場景,我們通過基礎資料中的目標IP地址去判斷dns劫持情況,這個目標IP地址是在建立連線的時候去採集的。如果第一個請求發生了dns劫持的情況,那這個請求我們能正常識別的dns劫持已經發生。如果後續的網路請求複用了這個連線,因為不會再去建立連線,所以基礎資料中沒有目標IP地址,這時候就需要使用事件序列資料中的連線複用事件中的連線的url和目標IP地址來判斷是不是被劫持的請求。

如何採集資料

位元組碼插樁原理

位元組碼插樁涉及到Android的打包構建流程。首先我們看下Android應用程式的打包流程,如下圖:

 

 

從上圖可知,我們只需要在 javac 之後 dex 之前遍歷所有的位元組碼檔案,並按照一定的規則過濾修改就可以實現位元組碼的插樁。

 

從Android Gradle 1.5.0 開始,Google官方提供了Transform API。通過Transform API,允許第三方以外掛的形式,在Android應用程式打包成dex檔案之前的編譯過程中操作.class檔案。

 

 

Android編譯器中的TaskManager將每個Transform串起來,第一個Transform接收來自javac編譯的結果,以及已經拉取到本地的第三方sdk(jar、aar),還有resource資源。這些編譯的中間產物,在Transform組成的鏈條上流動,每個Transform節點可以對class進行處理再傳遞給下一個Transform。常見的混淆、Desugar等的實現就是封裝在一個個Transform中。而自定義的Tranform會插入到這個Transform鏈條的最前面,所以開啟混淆的情況下通過自定義Transform對位元組碼進行修改也是先修改位元組碼再混淆。

 

網路庫調研

除了系統自帶的網路庫HttpUrlConnection,在android平臺還有很多優秀的第三方網路庫,大部分App開發會使用第三方的網路庫來發起網路請求。

 

從上表中主流網路庫的底層實現來看,我們只要支援OkHttp、HttpUrlConnection和HttpClinet的資料採集就能滿足主流網路庫的效能監控需求。

 

 

我們對應用市場上Top1000的App進行了分析,按整合數量排序依次是okhttp3&okhttp4、volley(HttpUrlConnection)、okhttp2和httpclient。其中okhttp網路庫佔比將近80%,所以我們優先實現了okhttp網路庫的監控實現。

 

okhttp網路庫的監控實現

okhttp網路庫家族主要包括okhttp2、okhttp3和okhttp4。其中okhttp3版本分佈眾多,底層實現變化也最多,而okhttp2的底層實現和okhttp3的早期版本相近,okhttp4是okhttp3的kotlin版本的實現。所以我們主要介紹下okhttp3上的監控實現。

 

 

上圖是okhttp3.12.0版本的實現框架,我們在網路庫的具體邏輯裡注入程式碼來採集需要的資料。

okhttp3版本眾多,從3.0.0-3.14.9已經有超過40個版本,對於每一個程式碼注入的位置都需要確保再各個版本上能正常工作。所以實現okhttp3的無痕埋點,版本適配需要耗費大量的工作。

 

資料上報

資料上報,除了需要考慮加密、鑑權、壓縮等方面,還需要能確保儘可能少的丟失日誌,同時還需要控制資源的佔用來降低對上層業務的影響。具體實現主要包括兩方面:

  • 快取:支援記憶體快取和磁碟快取兩級快取。需要實現業務隔離,多個業務使用快取功能時可以做到互不影響。

  • 上報:由於APM產生的日誌較多,為了控制併發數和記憶體,我們使用了一個業務共享的執行緒池和排程佇列。排程佇列最多快取10條批量日誌,如果超出10條會立即將日誌放入磁碟快取。另外在上報前提供了日誌預處理的開放介面方便業務層對日誌做處理,比如抽樣、聚合等功能。

 

後續計劃

EMAS網路效能監控已經對外開放,產品詳情:https://www.aliyun.com/product/emascrash/apm,後續我們會根據客戶實際需求去逐步完善功能。下一步計劃實現的需求包括:

  • 支援HttpUrlConnection、HttpClient等網路庫。

  • 支援body資料的採集上報,讓客戶可以感知、定位和解決在網路連通性正常,但服務端下發異常資料導致端上業務出現異常的問題。

  • 支援日誌資料端上預聚合,降低服務端儲存壓力。

  • 支援socket請求的監控。

 

歡迎大家積極留言,提出你們的寶貴意見和建議,非常感謝!釘釘搜尋35248489,加入阿里云云原生應用研發平臺EMAS技術交流群,探討最新最熱門的應用研發技術和實踐。

&n