網絡優化

網絡基礎知識

一、無線網絡

千兆級 LTE 指的是蜂窩網絡在理論上的速度能夠達到光纖級別的 1Gbps(125MB/s)。html

關於 5G 的原理:文章java

二、Link Turbo

此爲手機廠商的網絡優化,例如華爲最近在榮耀 V20 推出的 Link Turbo 網絡聚合加速技術linux

雙通道技術,能夠在 WiFi 網絡不穩定的時候,自動切換到移動網絡。相似的技術有:iPhone 的無限網絡助理、小米和一加的自適應 WLAN。android

可是雙通道技術,同時依然只能使用單一通道,只是會根據網絡狀況自動切換。而 Link Turbo 硬核的地方在於,能夠同時使用兩條通道傳輸數據,並且支持 TCP 和 UDP。其中 TCP 使用開源的 MultiPath TCP(iOS 7 也在引用),而 UDP 則是華爲自研的 MultiPath UDP。git

Link Turbo 的缺點:github

  • 覆蓋用戶比較少。
  • 須要後臺服務器同步支持。

Link Turbo 的意義:web

  • 流量愈來愈便宜,用戶會更願意追求體驗。
  • 華爲能夠直接和雲服務商以及 CDN 服務商合做,屏蔽應用後臺服務器的改造,下降集成成本。

網絡 I/O

一、I/O 模型

Linux 內核會把全部外部設備都看做一個文件來操做。在網絡 I/O 中系統對一個 Socket 的讀寫也會有相應的描述符,稱爲 socket fd(Socket 描述符)。算法

整個 I/O 流程分爲兩個階段:spring

等待 Socket 數據準備好。 將數據從內核拷貝到應用進程。編程

在 《UNIX 網路編程》 中,將 UNIX 網絡 I/O 模型分爲如下五種。

在開發中,比較經常使用的有:

  • 阻塞 I/O
  • 非阻塞 I/O
  • 多路複用 I/O

關於 UNIX 網絡 I/O 模型,能夠參考:

關於網絡,存在的幾個問題:

多路複用 I/O 必定比阻塞 I/O 更好?

和文件 I/O 同樣,最簡單的 I/O 併發方式就是多線程 + 阻塞 I/O。若是同時活動的網絡鏈接很是多,使用多路複用 I/O 性能的確會更好。可是對於客戶端來講,這個假設不必定成立,對於多路複用 I/O 來講,整個流程會增長大量的 select/epoll 這樣的系統調用,不必定比阻塞 I/O 更快。

epoll 必定比 select/poll 要好?

若是同一時間的鏈接數很是少的狀況,select 的性能不會比 epoll 好,可是更多的狀況下,epoll 更好。

epoll 使用了 mmap 減小內核到用戶空間的拷貝?epoll 並無使用 mmap 技術,參考 epoll 實現。而且也不會如此設計,由於直接共享內存可能會引起比較大的安全漏洞。

二、數據處理

網絡 I/O 也使用了終端,不過網絡 I/O 的終端更加複雜一些,同時使用了軟中斷和硬中斷。經過硬中斷通知 CPU 有數據來了,可是這個處理會很是輕量,耗時的操做被移到軟終端處理函數中慢慢處理。

  • 軟終端:經過 /proc/softirqs 文件
  • 硬中斷:經過 /proc/interrupts 文件。

網卡收發包的流程:

網絡性能評估

一、延遲與帶寬

延遲:數據從信息源發送到目的地所需的時間。 帶寬:邏輯或物理通訊路徑最大的吞吐量。

弱網的特色:

二、性能測量

指標:

  • 吞吐量:接收和傳輸的每秒字節數。
  • 延遲:發送/接收延遲、鏈接延遲、首包延遲、網絡往返時間等。
  • 鏈接數:每秒的鏈接數。
  • 錯誤:丟包計數、超時等。

Linux 提供了大量的網絡性能分析工具,比較適用 Android 的有如下幾種。

能夠直接查看 /proc/net,它裏面包含了許多網絡統計信息的文件。例如 Android 的 TrafficStats 接口,就是利用 /proc/net/xt_qtaguid/stats 和 /proc/net/xt_qtaguid/iface_stat_fmt 文件來統計應用的流量信息。

移動端優化

網絡優化的核心三問題:

除了這三個問題,還須要關心:耗電、流量。

整個網絡請求,主要分幾個步驟:

  • DNS 解析。經過 DNS 服務器,拿到對應域名的 IP 地址。比較關注:DNS 解析耗時狀況、運營商 LocalNDS 的劫持、DNS 調度等問題。
  • 建立鏈接。和服務器創建鏈接,包括 TCP 三次握手、TLS 密鑰協商等工做。多個 IP/端口該如何選擇、是否要使用 HTTPS、可否能夠減小甚至省下建立鏈接的時間,這些問題是優化的關鍵。
  • 發送/接收數據。關鍵點:組裝數據、發送數據、接收數據、解析數據,主要關注如何根據網絡情況,將帶寬利用好,怎樣快速檢測到網絡延遲,在弱網下如何調整包大小等問題。
  • 關閉鏈接。關注:主動關閉和被動關閉兩種狀況。

一個網絡庫的核心做用主要有如下三點:

  • 統一編程接口。
  • 全局網絡控制。統一的網絡調度、流量監控以及容災管理等。
  • 高性能。關注:速度、CPU、內存、I/O 的使用,以及失敗率、崩潰率、協議兼容性等方面。

比較好的網絡庫:

  • OkHttp
  • Chromium 的 Cronet
  • 微信的 Mars

商業軟件的應用:

  • Chromium:蘑菇街、頭條、UC 瀏覽器。
  • Mars:微信、拼多多、虎牙、鏈家、美麗說。

對比:

對於不用 OkHTTP,主要緣由在於不支持跨平臺。對於大型應用來講,跨平臺是很是重要的。

對於 Mars,它是一個跨平臺的 Socket 層解決方案,並不支持完整的 HTTP 協議,因此 Mars 從嚴格意義上來講,並非一個完整的網絡庫。可是它在弱網和鏈接上作了大量的優化,而且支持長鏈接。參考:Wiki

Chromium 沒有太大的缺點,而且還能夠享受 Google 後續網絡優化的成功,相似 TLS 1.三、QUIC 支持等。可是它針對弱網沒有作太多定製的華油,也不支持長鏈接。一般基於 Chromium 的二次開發,都是爲了解決這兩個問題。

大網絡平臺 對於大公司,不知足於客戶端優化,還會在服務端上作雙端優化。

一、HTTPDNS

DNS 的解析是咱們網絡請求的第一項工做,默認使用運營商的 LocalDNS 服務,這塊的耗時,在 3G 網絡下多是 200~300ms,4G 網路也須要 100ms。

LocalDNS 慢不是最大的問題,還存在一些其餘的問題:

  • 穩定性。UDP 協議,無狀態。容易域名劫持,每一年至少幾百萬個域名被劫持,一年至少十次大規模事件。
  • 準確性。LocalNDS 調度常常不許確。
  • 及時性。運營商會修改 DNS 的 TTL。致使 DNS 修改生效延遲。
  • HTTPDNS 就是爲了解決 LocalDNS 的這些問題。

參考百度的 《DNS 優化》

二、鏈接複用

建立鏈接須要通過:

  • TCP 三次握手
  • TLS 密鑰協商

創建鏈接的代價很是大,這裏的優化思路主要是複用鏈接,這樣不用每次請求都創建鏈接。

鏈接複用主要是利用 HTTP 協議裏的 keep-alive,而且 Http 2.0 的多路複用則能夠進一步提高鏈接複用率。它複用的這條鏈接支持同時處理多條請求,全部請求均可以併發在這條鏈接上進行。

HTTP 2.0 的多路複用的問題:

  • 同一條 Http 2.0 鏈接,只支持同一個域名。
  • 後端須要爲了支持 HTTP 2.0 額外改造。

爲了解決這兩個問題,一般會在統一接入層作改造,接入層將數據轉換到 HTTP/1.1 再轉發到對應域名的服務器。

HTTP 2.0 的多路複用,本質上依然是同一條 TCP 鏈接,若是全部的域名的請求都集中在某一條鏈接中,在網路擁塞的時候,容易出現 TCP 隊首阻塞問題。

對於客戶端網絡庫,OkHttp 和 Chromium 對於 HTTP/2.0 的鏈接,同一個域名只會保留一條鏈接。如遇到第三方請求,特別是文件下載以及視頻播放等場景,可能會遇到對方服務器單鏈接限速的問題,此處能夠經過修改網絡庫,或者簡單禁用掉 HTTP/2.0 協議解決。

三、壓縮與加密

壓縮能夠減小傳輸的數據量,對於 HTTP 請求來講,數據主要包括三部分:

  • 請求 URL
  • 請求 Header
  • 請求 Body

對於 Header,HTTP 2.0 自己支持頭部壓縮技術,所以須要壓縮的主要是 URL 和 請求 body。

壓縮的優化主要思路,是把重複的內容都優化掉。對於 URL,通常會帶不少公共參數,這些參數大部分是不變的,這樣不變的參數客戶端只要上傳一次便可。

對於請求 Body 來講,一方面是數據通訊協議的選擇,在網絡傳輸中目前最流行的兩種數據序列化的方式是 JSON 和 Protocol Buffers。Protocol Buffers 在使用上會複雜一些,可是數據壓縮率、序列化和反序列化速度上有很大的優點。

另一方面是壓縮算法的選擇:

其中,若是 Z-standard 經過業務數據樣本訓練處合適的字典,是目前壓縮率表現最好的算法。

針對特殊的數據,還有一些針對性的壓縮方法,例如圖片有 webp、hevc、SharpP 等壓縮率更高的格式。除此以外,還有基於 AI 的圖片超清化也是一大神器。

安全

基於 HTTPS 和 HTTP/2 通道,已經有了 TLS 加密。參考《TLS 協議分析》

HTTPS 的優化思路:

  • 鏈接複用率。經過多個域名共用同一個 HTTP/2 鏈接、長鏈接等方式提高鏈接複用率。

  • 減小握手次數。TLS 1.3 能夠實現 0—RTT 協商。0-RTT 在 TLS 1.3 以前已經被大廠所使用,例如微信的 mmtls、Facebook 的 fizz、阿里的 SlightSSL。

  • 性能提高。使用 ecc 證書代替 RSA,服務端簽名的性能能夠提高 4~10 倍,可是客戶端校驗性能下降了約 20 倍,從 10 微秒級下降到 100 微秒級。另一方面能夠經過 Session Ticket 會話複用,節省一個 RTT 耗時。

若是客戶端設置了代理,TLS 加密的數據能夠被揭開並可能被利用,此時能夠在客戶端使用「證書鎖定」。

還有一些方案,多是須要用錢堆出來,好比部署跨國的專線、加速點、多 IDC 就近接入等,除此以外,使用 CDN 服務P2P技術也是比較常見的手段。

QUIC 和 IPv6

QUIC 最先在 2013 年被 Google 實現,在 2018 年,基於 QUIC 的思想,又重寫了一套 QUIC 協議,被 HTTP 確認爲 HTTP 3.0 標準。

QUIC 能夠簡單理解爲:HTTP 2.0 + TLS 1.3 + UDP。

QUIC 的優點:

  • 靈活控制擁塞協議。能夠直接使用 Google 的 BBR 算法。
  • 「真」鏈接複用。客戶端切換網絡時,不須要重連。

QUIC 現存的問題:

  • 建立鏈接成功率低。UDP 的穿透性,NAT 局域網路由、交換機、防火牆等會禁止 UDP 443 通訊,目前 QUIC 在國內建連的成功率大約在 95% 左右。
  • 運營商支持。運營商針對 UDP 通道支持不足,表現不穩定,例如 QoS 限速丟包,有些小運營商甚至不支持 UDP 包。

大廠的 QUIC 實踐:騰訊微博阿里

IPv6 在中國一直很是沉寂,2017 年 IPv6 支持報告,中國只有 0.38% 的用戶使用 IPv6。

2018 年,使用 IPv6 的中國用戶已經增加到 3.15%,參考:《2018 年度 ipV6報告

IPv6 必定是從此的去世,推動 IPv6 後,大量的 IP 地址意味着能夠告別各類 NAT、P2P、QUIC 的鏈接問題,阿里雲和騰訊雲,都作了大量 IPv6 的支持 工做。

微信客戶端怎樣應對弱網絡

阿里以及日活網管通道架構演進

阿里巴巴 HTTP 2.0 實踐及無線通訊協議的演進之路

移動端監控

一、如何監控網絡

插樁的方式,360 開源的性能工具 ArgusAPM 就是利用 Aspect 切換插樁,實現監控系統和 OkHttp 網絡庫的請求。

系統網絡庫的插樁實現,能夠參考 TraceNetTrafficMonitor,主要利用 Aspect 的切面功能,關於 OkHttp 的攔截器能夠參考 OkHttp3Aspect,它會更加簡單一些,由於 OkHttp 自己有代理機制。

@Pointcut("call(public okhttp3.OkHttpClient build())")
public void build() {
}

@Around("build()")
public Object aroundBuild(ProceedingJoinPoint joinPoint) throws Throwable {
    Object target = joinPoint.getTarget();
    if (target instanceof OkHttpClient.Builder &&    Client.isTaskRunning(ApmTask.TASK_NET)) {
        OkHttpClient.Builder builder = (OkHttpClient.Builder) target;
        builder.addInterceptor(new NetWorkInterceptor());
    }
    return joinPoint.proceed();
}
複製代碼

插樁的缺點,主要在於不全面,非系統和 OkHttp 網絡庫,以及 Native 代碼的網絡請求,都沒法被監控到。

Native Hook,相關方法:

鏈接相關:connect 發送數據相關:send 和 sendto 接受數據相關:recv 和 recvfrom

Socket 建連的堆棧以下:

java.net.PlainSocketImpl.socketConnect(Native Method)
java.net.AbstractPlainSocketImpl.doConnect
java.net.AbstractPlainSocketImpl.connectToAddress
java.net.AbstractPlainSocketImpl.connect
java.net.SocksSocketImpl.connect
java.net.Socket.connect
com.android.okhttp.internal.Platform.connectSocket
com.android.okhttp.Connection.connectSocket
com.android.okhttp.Connection.connect
複製代碼

統一網絡庫。

二、如何監控流量

監控流量,能夠經過 TrafficStats 類,它是 Android Api 8 加入的接口,用於獲取整個手機或者某個 UID 從開機算起的網路流量。參考 Facebook 的開源庫 network-connect-class

getMobileRxBytes()        // 從開機開始 Mobile 網絡接收的字節總數,不包括 Wifi
getTotalRxBytes()         // 從開機開始全部網絡接收的字節總數,包括 Wifi
getMobileTxBytes()        // 從開機開始 Mobile 網絡發送的字節總數,不包括 Wifi
getTotalTxBytes()         // 從開機開始全部網絡發送的字節總數,包括 Wifi
複製代碼
// stats 接口提供各個 uid 在各個網絡接口(wlan0, ppp0 等)的流量信息
/proc/net/xt_qtaguid/stats
// iface_stat_fmt 接口提供各個接口的彙總流量信息
proc/net/xt_qtaguid/iface_stat_fmt
複製代碼

TrafficStats 的工做原理,是利用 Linux 內核的統計接口,/proc/net/xt_qtaguid/stats 和 /proc/net/xt_qtaguid/iface_stat_fmt 對這兩個接口進行讀取和分析。Android 7.0 以後,已經不讓開發者直接去讀取 stats 文件,只能經過 TrafficStats 獲取本身應用的流量信息。

手機的網絡測試模式:

  • iPhone:「3001#12345#」
  • Android:「##4636##」

對於廠商,能夠拿到更多的網絡信息:

  • 網卡驅動層信息。如射頻參數,用來判斷 WiFi 的新號強度;網卡數據包隊列長度,用來判斷網絡是否擁塞。
  • 協議棧信息,獲取數據包發送、接受、時延和丟包信息。

大網絡平臺監控

網絡問題的監控存在的問題:

  • 實時性。容易流失現場。
  • 複雜性。不一樣國家地區、運營商等都有可能不太。
  • 鏈路長。整個請求鏈路很是長,任何環節均可能出現問題。

監控主要從幾個方面考量:

  • 客戶端監控。時延、維度、錯誤。
  • 接入層監控。實時性、可靠性。
  • 監控報警。實時監控、離線監控。
相關文章
相關標籤/搜索