現代移動端網絡短鏈接的優化手段總結:請求速度、弱網適應、安全保障

一、前言

衆所周之,一般咱們開發一個移動端應用,會直接調用系統提供的網絡請求接口去服務端請求數據,再針對返回的數據進行一些處理,或者使用iOS中的開源AFNetworking/OKHttp這樣的網絡庫(Android中能夠用HttpURLConnection或者開源的okhttp庫),管理好請求線程和隊列,再自動作一些數據解析,就結束了。html

但對於追求用戶體驗的應用來講,還會針對移動網絡的特性作進一步優化,包括:前端

1)速度優化:網絡請求的速度怎樣能進一步提高?git

2)弱網適應:移動端網絡環境隨時變化,常常出現網絡鏈接很不穩定可用性差的狀況,怎樣在這種狀況下最大限度最快地成功請求?github

3)安全保障:怎樣防止被第三方竊聽/篡改或冒充,防止運營商劫持,同時又不影響性能?算法

對基於瀏覽器的前端開發來講,網絡這塊能作的事情不多,但對於原生的移動端應用來講(本文中說的原生主要指iOS和Android應用),整個網絡請求過程是自由控制的,能夠作不少事情。不少大型 APP 都針對這三個問題作了不少網絡層的優化,一些新的網絡層協議像 HTTP2 / QUIC 也是在這些方面進行了很多優化。在此請跟着個人文字,邊學習邊整理,總結一下當今主流的移動端網絡短鏈接常見優化手段,但願能給您帶來啓發。編程

本文整理的有關內容,對於移動端即時通信IM應用來講,一樣具備啓發意義,由於現今主流的移動端IM數據通訊總結下來無外乎就是長鏈接+短鏈接的方式,則短鏈接的優化在某些場景下對於移動端IM來講可能顯示的更爲特出。在這方面,微信作的比較完全和極端,幾乎再造了一套針對移動端IM的網絡層框架(詳見:《如約而至:微信自用的移動端IM網絡層跨平臺組件庫Mars已正式開源》)。json

(本文同步發佈於:www.52im.net/thread-1413…瀏覽器

二、相關文章

1)關於網絡通訊的基礎文章:緩存

若是您對網絡通訊知識瞭解甚少,建議閱讀《網絡編程懶人入門系列文章》,更高深的網絡通訊文章能夠閱讀《鮮爲人知的網絡編程系列文章》。安全

2)涉及移動端網絡特性的文章:

談談移動端 IM 開發中登陸請求的優化

移動端IM開發須要面對的技術問題(含通訊協議選擇)

簡述移動端IM開發的那些坑:架構設計、通訊協議和客戶端

微信對網絡影響的技術試驗及分析(論文全文)

騰訊原創分享(一):如何大幅提高移動網絡下手機QQ的圖片傳輸速度和成功率

騰訊原創分享(二):如何大幅壓縮移動網絡下APP的流量消耗(上篇)

騰訊原創分享(二):如何大幅壓縮移動網絡下APP的流量消耗(下篇)

如約而至:微信自用的移動端IM網絡層跨平臺組件庫Mars已正式開源

三、關於做者

本文原始內容來自JSPatch開源工程做者bang的技術分享,他的博客是:blog.cnbang.net/about/,本次內容有優化和完善,感謝原做者的無私分享。

四、請求速度的優化

正常一條網絡請求須要通過的流程是這樣:

1)DNS 解析,請求DNS服務器,獲取域名對應的 IP 地址;

2)與服務端創建鏈接,包括 tcp 三次握手,安全協議同步流程;

3)鏈接創建完成,發送和接收數據,解碼數據。

這裏有明顯的三個優化點:

1)直接使用 IP 地址,去除 DNS 解析步驟;

2)不要每次請求都從新創建鏈接,複用鏈接或一直使用同一條鏈接(長鏈接);

3)壓縮數據,減少傳輸的數據大小。

逐條來看能作什麼。

4.1 DNS優化

DNS 完整的解析流程很長,會先從本地系統緩存取,若沒有就到最近的 DNS 服務器取,若沒有再到主域名服務器取,每一層都有緩存,但爲了域名解析的實時性,每一層緩存都有過時時間。

上面這種 DNS 解析機制有幾個缺點:

1)緩存時間設置得長,域名更新不及時,設置得短,大量 DNS 解析請求影響請求速度;

2)域名劫持,容易被中間人攻擊,或被運營商劫持,把域名解析到第三方 IP 地址,據統計劫持率會達到7%;

3)DNS 解析過程不受控制,沒法保證解析到最快的IP;

4)一次請求只能解析一個域名。

爲了解決這些問題,就有了 HTTPDNS,原理很簡單,就是本身作域名解析的工做,經過 HTTP 請求後臺去拿到域名對應的 IP 地址,直接解決上述全部問題。

自已實現HTTPDNS的好處總結就是:

1)域名解析與請求分離,全部請求都直接用IP地址,無需 DNS 解析,APP 定時請求 HTTPDNS 服務器更新IP地址便可;

2)經過簽名等方式,保證 HTTPDNS 請求的安全,避免被劫持;

3)DNS 解析由本身控制,能夠確保根據用戶所在地返回就近的 IP 地址,或根據客戶端測速結果使用速度最快的 IP;

4)一次請求能夠解析多個域名。

其他細節就很少說了,HTTPDNS 優勢這麼多,幾乎成爲中大型 APP 的標配。至此解決了第一個問題 — DNS 解析耗時的問題,順便把一部分安全問題 — DNS 劫持也解決了。

關於移動端網絡中DNS的問題,《談談移動端 IM 開發中登陸請求的優化》一文中也有提到,僅供參考。

4.2 鏈接的優化

第二個問題,鏈接創建耗時的問題,這裏主要的優化思路是複用鏈接,不用每次請求都從新創建鏈接,如何更有效率地複用鏈接,能夠說是網絡請求速度優化裏最主要的點了,而且這裏的優化仍在演進過程當中,值得了解下。

▼【keep-alive】:

HTTP 協議裏有個 keep-alive,HTTP1.1默認開啓,必定程度上緩解了每次請求都要進行TCP三次握手創建鏈接的耗時。原理是請求完成後不當即釋放鏈接,而是放入鏈接池中,若這時有另外一個請求要發出,請求的域名和端口是同樣的,就直接拿出鏈接池中的鏈接進行發送和接收數據,少了創建鏈接的耗時。

實際上如今不管是客戶端仍是瀏覽器都默認開啓了keep-alive,對同個域名不會再有每發一個請求就進行一次建連的狀況,純短鏈接已經不存在了。但有個問題,就是這個 keep-alive 的鏈接一次只能發送接收一個請求,在上一個請求處理完成以前,沒法接受新的請求。若同時發起多個請求,就有兩種狀況:

若串行發送請求,能夠一直複用一個鏈接,但速度很慢,每一個請求都要等待上個請求完成再進行發送。

若並行發送這些請求,那麼首次每一個請求都要進行tcp三次握手創建新的鏈接,雖然第二次能夠複用鏈接池裏這堆鏈接,但若鏈接池裏保持的鏈接過多,對服務端資源產生較大浪費,若限制了保持的鏈接數,並行請求裏超出的鏈接仍每次要建連。

對這個問題,新一代協議 HTTP2 提出了多路複用去解決。

PS:關於理解TCP的3次握手原理,如下文章可能對您會有幫助

TCP/IP詳解 - 第18章·TCP鏈接的創建與終止

理論經典:TCP協議的3次握手與4次揮手過程詳解

理論聯繫實際:Wireshark抓包分析TCP 3次握手、4次揮手過程

通俗易懂-深刻理解TCP協議(上):理論基礎

▼【多路複用】:

HTTP2 的多路複用機制同樣是複用鏈接,但它複用的這條鏈接支持同時處理多條請求,全部請求均可以併發在這條鏈接上進行,也就解決了上面說的併發請求須要創建多條鏈接帶來的問題。

網絡上有張圖能夠較形象地表現這個過程:

HTTP1.1的協議裏,在一個鏈接裏傳送數據都是串行順序傳送的,必須等上一個請求所有處理完後,下一個請求才能進行處理,致使這些請求期間這條鏈接並非滿帶寬傳輸的,即便是HTTP1.1的pipelining能夠同時發送多個request,但response還是按請求的順序串行返回,只要其中一個請求的response稍微大一點或發生錯誤,就會阻塞住後面的請求。

HTTP2 這裏的多路複用協議解決了這些問題,它把在鏈接裏傳輸的數據都封裝成一個個stream,每一個stream都有標識,stream的發送和接收能夠是亂序的,不依賴順序,也就不會有阻塞的問題,接收端能夠根據stream的標識去區分屬於哪一個請求,再進行數據拼接,獲得最終數據。

解釋下多路複用這個詞,多路能夠認爲是多個鏈接,多個操做,複用就是字面上的意思,複用一條鏈接或一個線程。HTTP2這裏是鏈接的多路複用,網絡相關的還有一個I/O的多路複用(select/epoll),指經過事件驅動的方式讓多個網絡請求返回的數據在同一條線程裏完成讀寫。

移動客戶端來講,iOS 9 以上 NSURLSession 已原生支持 HTTP2,只要服務端也支持就能夠直接使用,Android 的開源網絡庫 okhttp3以上版本也支持了 HTTP2,國內一些大型 APP 會自建網絡層,支持 HTTP2 的多路複用,避免系統的限制以及根據自身業務須要增長一些特性,例如微信的開源網絡庫 mars(詳見《如約而至:微信自用的移動端IM網絡層跨平臺組件庫Mars已正式開源》),作到一條長鏈接處理微信上的大部分請求,多路複用的特性上基本跟 HTTP2 一致。

▼【TCP隊頭阻塞】:

HTTP2 的多路複用看起來是完美的解決方案,但還有個問題,就是隊頭阻塞,這是受限於 TCP 協議,TCP 協議爲了保證數據的可靠性,若傳輸過程當中一個 TCP 包丟失,會等待這個包重傳後,纔會處理後續的包。HTTP2的多路複用讓全部請求都在同一條鏈接進行,中間有一個包丟失,就會阻塞等待重傳,全部請求也就被阻塞了。

對於這個問題不改變 TCP 協議就沒法優化,但 TCP 協議依賴操做系統實現以及部分硬件的定製,改進緩慢,因而 GOOGLE 提出 QUIC 協議(詳見《技術掃盲:新一代基於UDP的低延時網絡傳輸層協議——QUIC詳解》),至關於在 UDP 協議之上再定義一套可靠傳輸協議,解決 TCP 的一些缺陷,包括隊頭阻塞。具體解決原理網上資料較多,能夠看看。

QUIC 處於起步階段,少有客戶端接入,QUIC 協議相對於 HTTP2 最大的優點是對TCP隊頭阻塞的解決,其餘的像安全握手 0RTT / 證書壓縮等優化 TLS1.3 已跟進,能夠用於 HTTP2,並非獨有特性。TCP 隊頭阻塞在 HTTP2 上對性能的影響有多大,在速度上 QUIC 能帶來多大提高待研究(關於這一點能夠看看騰訊的QUIC技術實踐《讓互聯網更快:新一代QUIC協議在騰訊的技術實踐分享》)。

PS:關於新一代QUIC協議的更多文章請見

技術掃盲:新一代基於UDP的低延時網絡傳輸層協議——QUIC詳解

讓互聯網更快:新一代QUIC協議在騰訊的技術實踐分享

七牛雲技術分享:使用QUIC協議實現實時視頻直播0卡頓!

4.3 數據壓縮優化

第三個問題,傳輸數據大小的問題。數據對請求速度的影響分兩方面,一是壓縮率,二是解壓序列化反序列化的速度。目前最流行的兩種數據格式是 json 和 protobuf,json 是字符串,protobuf 是二進制,即便用各類壓縮算法壓縮後,protobuf 仍會比 json 小,數據量上 protobuf 有優點,序列化速度 protobuf 也有一些優點,這二者的對比就不細說了。(關於protobuf的原理,詳見《Protobuf通訊協議詳解:代碼演示、詳細原理介紹等》、《全方位評測:Protobuf性能到底有沒有比JSON快5倍?》、《強列建議將Protobuf做爲你的即時通信應用數據傳輸格式》)

壓縮算法多種多樣,也在不斷演進,最新出的 Brotli 和Z-standard實現了更高的壓縮率,Z-standard 能夠根據業務數據樣本訓練出適合的字典,進一步提升壓縮率,目前壓縮率表現最好的算法。

除了傳輸的 body 數據,每一個請求 HTTP 協議頭的數據也是不可忽視,HTTP2 裏對 HTTP 協議頭也進行了壓縮,HTTP 頭大可能是重複數據,固定的字段如 method 能夠用靜態字典,不固定但多個請求重複的字段例如 cookie 用動態字典,能夠達到很是高的壓縮率,這裏有詳細介紹《HTTP/2 頭部壓縮技術介紹》(該做者針對HTTP2有不少研究,更多HTTP2文章可見做者的HTTP2技術專題,方便進行深刻學習)。

經過 HTTPDNS,鏈接多路複用,更好的數據壓縮算法,能夠把網絡請求的速度優化到較不錯的程度了,接下來再看看弱網和安全上能夠作的事情。

五、針對移動弱網的優化

手機無線網絡環境不穩定,針對弱網的優化,微信有較多實踐和分享,包括:

1)提高鏈接成功率:

複合鏈接,創建鏈接時,階梯式併發鏈接,其中一條連通後其餘鏈接都關閉。這個方案結合串行和併發的優點,提升弱網下的鏈接成功率,同時又不會增長服務器資源消耗,見下圖

2)制定最合適的超時時間:

對總讀寫超時(從請求到響應的超時)、首包超時、包包超時(兩個數據段之間的超時)時間制定不一樣的計算方案,加快對超時的判斷,減小等待時間,儘早重試。這裏的超時時間還能夠根據網絡狀態動態設定;

3)調優TCP參數,使用TCP優化算法:

對服務端的TCP協議參數進行調優,以及開啓各類優化算法,使得適合業務特性和移動端網絡環境,包括RTO初始值,混合慢啓動,TLP,F-RTO等。

針對弱網的這些細緻優化未成爲標準,系統網絡庫沒有內置,不過前兩個客戶端優化微信的開源網絡庫 mars 有實現,如有須要可使用(詳見《如約而至:微信自用的移動端IM網絡層跨平臺組件庫Mars已正式開源》)。

六、安全方面

標準協議 TLS 保證了網絡傳輸的安全,前身是 SSL,不斷在演進,目前最新是 TLS1.3。常見的 HTTPS 就是 HTTP 協議加上 TLS 安全協議。

安全協議歸納性地說解決兩個問題:

1)保證安全;

2) 下降加密成本。

在保證安全上:

1)使用加密算法組合對傳輸數據加密,避免被竊聽和篡改;

2)認證對方身份,避免被第三方冒充;

3)加密算法保持靈活可更新,防止定死算法被破解後沒法更換,禁用已被破解的算法。

下降加密成本上:

1)用對稱加密算法加密傳輸數據,解決非對稱加密算法的性能低以及長度限制問題;

2)緩存安全協議握手後的密鑰等數據,加快第二次建連的速度;

3)加快握手過程:2RTT-> 0RTT。加快握手的思路,就是本來客戶端和服務端須要協商使用什麼算法後才能加密發送數據,變成經過內置的公鑰和默認的算法,在握手的同時就把數據發出去,也就是不須要等待握手就開始發送數據,達到0RTT。

這些點涉及的細節很是多,對 TLS 的介紹有一篇雄文,說得很詳細,在此推薦:《TLS協議分析 與 現代加密通訊協議設計》(JackJiang注:這篇文章長的驚人,但願你能耐心把它看完 ^_^)。

下面這幾篇是有關移動端通訊安全的基礎文章,比上面那篇要容易理解:

即時通信安全篇(三):經常使用加解密算法與通信安全講解

即時通信安全篇(六):非對稱加密技術的原理與應用實踐

傳輸層安全協議SSL/TLS的Java平臺實現簡介和Demo演示

微信新一代通訊安全解決方案:基於TLS1.3的MMTLS詳解

來自阿里OpenIM:打造安全可靠即時通信服務的技術實踐分享

通俗易懂:一篇掌握即時通信的消息傳輸安全原理

目前基本主流都支持 TLS1.2,iOS 網絡庫默認使用 TLS1.2,Android4.4 以上支持 1.2。TLS1.3 iOS 還處於測試階段,Android 未查到消息。對於普通 APP,只要正確配置證書,TLS1.2 已經能保證傳輸安全,只是在建連速度上會有所損耗,有一些大型 APP 像微信就自行實現了 TLS1.3 的部分協議,早一步全平臺支持(微信團隊專門分享過關於TLS1.3的實踐文章,詳見《微信新一代通訊安全解決方案:基於TLS1.3的MMTLS詳解》)。

七、寫在最後

移動端網絡優化這個話題很是龐大,本文只是在學習過程當中從優化思路上列舉了目前業界常見的優化點,還有不少細節不少更深刻的優化沒涉及到,網絡層實踐開發經驗不足,如有錯誤歡迎指出。

(本文同步發佈於:www.52im.net/thread-1413…

相關文章
相關標籤/搜索