Android 網絡優化方案

2021-02-07 安卓開發精選

(給安卓開發精選加星標)

轉自:掘金-究極逮蝦戶

https://juejin.cn/post/6896302142542315533

面試官:小蝦啊,我好想你啊,你都好久沒來找我面試了呀。


小蝦:emmmmmmm,這不是怕被你打擊嗎。


面試官:ok,看來是有備而來,那麼我們今天聊聊網絡優化咋做吧。


小蝦:我大意了,沒有閃。老頭子,你不講武德,我奉勸你耗子尾汁。


如何優化一個網絡請求呢?


相信大家在面試的時候可能會被問到這個問題。今天我其實就是講述下我知道的一些簡單的優化方式,可以幫助大家在面試的過程中得到點基礎分數。


我們先從最簡單,大家比較容易了解到的講起。


DNS優化

DNS則是典型的應用層的協議了,至於說為什麼第二層能查第三層的IP,因為DNS是Domain Name System縮寫,所以你認為是服務是協1653議都可以。

一個Http請求在建立Tcp連接的過程中,肯定會產生一次DNS,那麼我們是不是可以通過內存緩存的方式,通過一個HashMap持有這個Host的IP,當下次發起Tcp連接的時候,我們就可以用直接用內存中的這個Ip,而不需要再去走一遍Dns服務了。


這個時候你肯定會問我,臥槽,你這個不是搞我嗎,這可怎麼改呀?


如果你的網絡層用的是OkHttp的話,Okhttp在封裝的時候就已經考慮到這個部分了,其內部提供了Dns的接口,可以讓外部在構造Client的時候傳入。


class HttpDns : Dns {
private val cacheHost = hashMapOf<String, InetAddress>()
override fun lookup(hostname: String): MutableList<InetAddress> { if (cacheHost.containsKey(hostname)) { cacheHost[hostname]?.apply { return mutableListOf(this) } } return try { InetAddress.getAllByName(hostname)?.first()?.apply { cacheHost[hostname] = this } mutableListOf(*InetAddress.getAllByName(hostname)) } catch (e: NullPointerException) { val unknownHostException = UnknownHostException("Broken system behaviour for dns lookup of $hostname") unknownHostException.initCause(e) throw unknownHostException } }}


這裡可以稍微給大家展開下,LocalDns是不可以被信任的,經常會有運營商會搞一些奇奇怪怪的Dns攔截,導致大家收到的請求是運營商所緩存的(目的是為了省流量),所以阿里騰訊等都有自己對外輸出的HttpDns的服務。這個服務可以幫助大家找到真實準確的Host的Ip,就是這個服務是收錢的。


如果你是個IOS開發人員,那麼你一定要注意SNI(Server Name Indication),一個IP對應多個多個Https證書的問題。


CacheControl


Http請求在1.1階段就引入了CacheControl了,通過CacheControl可以讓後端直接控制請求內容的緩存策略。所以還有比緩存更簡單粗暴的網絡優化方式嗎?

在http中,控制緩存開關的欄位有兩個:Pragma 和 Cache-Control。

通過圖片簡單的介紹下一些緩存參數。


如果說一句不負責任的話,這個只要後端大佬開啟CacheControl就好了呀,原生網絡庫本來就支持的。當然後端大佬一般都不是特別願意,其實各位安卓也可以通過添加OkHttp攔截器的方式給網絡請求添加一個統一的CacheControl,當然如果你有定製化的需求肯定還是要自己開發的,我這裡只負責科普下這個面試可以回答的地方,細節大家可以參考下這個倉庫。


HTTP協議規格說明定義ETag為「被請求變量的實體值」。另一種說法是,ETag是一個可以與Web資源關聯的記號(token)。典型的Web資源可以一個Web頁,但也可能是JSON或XML文檔。伺服器單獨負責判斷記號是什麼及其含義,並在HTTP響應頭中將其傳送到客戶端,以下是伺服器端返回的格式:ETag:"50b1c1d4f775c61:df3"客戶端的查詢更新格式是這樣的:If-None-Match : W / "50b1c1d4f775c61:df3"如果ETag沒改變,則返回狀態304然後不返回,這也和Last-Modified一樣。測試Etag主要在斷點下載時比較有用。

而我們只要使用了CacheControl,就可以用到ETag, 如果當數據內容沒有發生變更的情況下,就不會傳輸數據,這樣也可以給大家略微優化下你們的Api請求。


Http 1.0 - 1.1 - 1.X - 2.0


以下所有內容均來自網絡 HTTP1.0、HTTP1.1 和 HTTP2.0 的區別


當然我們還可以讓後端升級接口協議版本,這個可以明顯提升你請求響應性能。


長連接,HTTP 1.1支持長連接(PersistentConnection)和請求的流水線(Pipelining)處理,在一個TCP連接上可以傳送多個HTTP請求和響應,減少了建立和關閉連接的消耗和延遲,在HTTP1.1中默認開啟Connection:keep-alive,一定程度上彌補了HTTP1.0每次請求都要創建連接的缺點。

header壓縮,如上文中所言,對前面提到過HTTP1.x的header帶有大量信息,而且每次都要重複發送,HTTP2.0使用encoder來減少需要傳輸的header大小,通訊雙方各自cache一份header fields表,既避免了重複header的傳輸,又減小了需要傳輸的大小。

新的二進位格式(Binary Format),HTTP1.x的解析是基於文本。基於文本協議的格式解析存在天然缺陷,文本的表現形式有多樣性,要做到健壯性考慮的場景必然很多,二進位則不同,只認0和1的組合。基於這種考慮HTTP2.0的協議解析決定採用二進位格式,實現方便且健壯。

多路復用(MultiPlexing),即連接共享,即每一個request都是是用作連接共享機制的。一個request對應一個id,這樣一個連接上可以有多個request,每個連接的request可以隨機的混雜在一起,接收方可以根據request的 id將request再歸屬到各自不同的服務端請求裡面。

HTTP2.0的多路復用和HTTP1.X中的長連接復用有什麼區別?

HTTP/1.* 一次請求-響應,建立一個連接,用完關閉;每一個請求都要建立一個連接;

HTTP/1.1 Pipeling解決方式為,若干個請求排隊串行化單線程處理,後面的請求等待前面請求的返回才能獲得執行機會,一旦有某請求超時等,後續請求只能被阻塞,毫無辦法,也就是人們常說的線頭阻塞;

HTTP/2多個請求可同時在一個連接上並行執行。某個請求任務耗時嚴重,不會影響到其它連接的正常執行;

好了,下面要開始真的進入牛逼的東西了,前文你肯定以為我是個大水逼,複製黏貼。

GRPC( A high-performance, open-source universal RPC framework)
不知道各位有沒有聽說過一個都市怪談,字節的網絡庫優化有多厲害多厲害,網絡底層採用的是Webview底層的Chromium的網絡庫,在弱網情況下對於api的優化啥的,巴拉巴拉

Cronet是Chromium網絡引擎對不同作業系統做的封裝,實現了移動端應用層、表示層、會話層協議,支持HTTP1/2、SPDY、QUIC、WebSocket、FTP、DNS、TLS等協議標準。支持Android、IOS、Chrome OS、Fuchsia,部分支持Linux、MacOS、Windows桌面作業系統。實現了Brotli數據壓縮、預連接、DNS緩存、session復用等策略優化以及TCP fast open等系統優化。本文內容基於Chromium 75版本。

字節用的就是Chrome的cronet網絡庫(順便展開下,cronet同時支持ios,android,前端)。而由於grpc協議的問題,所以傳輸內容直接使用的protobuf格式,所以其不僅僅是網絡層上的優化,同時由於流能直接轉化成實體類,同時也減少了可序列化的時間。

protocol buffers 是一種語言無關、平臺無關、可擴展的序列化結構數據的方法,它可用於(數據)通信協議、數據存儲等。

Protocol Buffers 是一種靈活,高效,自動化機制的結構數據序列化方法-可類比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更為簡單。

你可以定義數據的結構,然後使用特殊生成的原始碼輕鬆的在各種數據流中使用各種語言進行編寫和讀取結構數據。你甚至可以更新數據結構,而不破壞由舊數據結構編譯的已部署程序。

但是正常的網絡框架基本都使用了Retrofit+Okhttp,而且大家都已經使用的很習慣了,所以我大膽的猜測,字節其實應該用OkHttp橋接了cronet。所以這樣基本就能無縫橋接當前已有的網絡庫了。


由GRRC升級QUIC

QUIC(Quick UDP Internet Connection)是谷歌制定的一種基於UDP的低時延的網際網路傳輸層協議。在2016年11月國際網際網路工程任務組(IETF)召開了第一次QUIC工作組會議,受到了業界的廣泛關注。這也意味著QUIC開始了它的標準化過程,成為新一代傳輸層協議

其實整個QUIC協議(Http3.0協議)本來就是谷歌寫的,所以谷歌的Cronet本身就支持這也是正常的。我其實之前就特地去查過OKHttp支持的協議內容,當前還是只停留在2.0階段,主要就還是因為當前的Connection寫的太好了,而且需要把Tcp直接更換成Udp,所以遲遲沒有更新3.0協議的支持。


所以各位如果想從協議層去做對應的優化,那麼可能OkHttp帶給大家的應該還是無盡的等待了。


還能幹嗎?


其實優化方面我的大概的姿勢點就這麼多了,但是我們可以考慮從監控方面的角度去再重新審視這個話題哦。客戶端請求從發起到網關實際接收到,其實中間有很複雜的鏈路,簡單的說,OKhttp內也走過了這麼多個攔截器了。但是當一個線上用戶反饋這個界面怎麼刷出來的這麼慢的情況下,我們以後端網關開始作為請求的開始節點,就會出現難以定位真實問題的情況。


基於OkHttp的網絡監控


我們是不是可以考慮把整個api發起到結束進行監控,從而可以方便線上去監控一個Api真實的發起到結束的狀況呢?我們先簡單的把一個請求的節點拆分下。我要盜圖了。

參考數據深入理解OkHttp3:(七)事件(Events)

基於OKHttp提供的EventListener,我們就可以對於一個請求發起到最後的各個節點進行監控,之後上報日誌數據,這樣在後續的撕逼過程中,其實就可以做到有理有據,有話可說,你真的慢了。


總結


這篇文章基本就存粹是為了各位應付面試用的,也算是我對於Android網絡優化的一些簡單的總結吧。其實中間能展開的內容也還是有的,就是需要各位自己去摸一摸了。


- EOF -



看完本文有收穫?請分享給更多人

 推薦關注「安卓開發精選」,提升安卓開發技術

點讚和在看就是最大的支持❤️

相關焦點

  • 幾乎是史上最全最實用的Android性能全面分析與優化方案研究
    分析問題:找到問題後,分析針對這個問題該如何解決,確定解決方案。解決問題:根據分析結果尋找解決方案。驗證問題:保證優化有效,沒有產生新的問題,以及產品穩定性。性能優化工具以下優化工具在下面文章中具體介紹使用方法。
  • Android應用耗電量分析與優化建議
    當我們的App在設備處於休眠狀態下想要執行一次網絡請求的時候;首先需要喚醒設備,接著會發送數據請求,然後等待服務端返回的結果,最後再經過一段時間的等待才會慢慢進入休眠狀態。設備休眠[http://www.cnblogs.com/kobe8/p/3819305.html])CPU和網絡耗電方面,主要是減少I/O操作(包括資料庫操作),大量的計算;減少網絡網絡請求次數和數據量,將不重要的操作放在用戶充電或已經連接至WiFi的時候。
  • Android Crash 案例解決方案
    IndexOutOfBoundsException 解決方案在使用時判斷對象內容是否為0.ActivityNotFoundException 解決方案在AndroidMainfest.xml中註冊即可IllegalStateException 解決方案IllegalStateException 類異常很多,不同的代碼會有不同的解決方案,上述舉例解決方案如下
  • android 復用 布局優化專題及常見問題 - CSDN
    在布局優化中,Androi的官方提到了這三種布局<include />、<merge />、<ViewStub />,並介紹了這三種布局各有的優勢,下面也是簡單說一下怎麼使用.
  • Android網絡優化攻略,簡單了解一下?
    所以還有比緩存更簡單粗暴的網絡優化方式嗎?在http中,控制緩存開關的欄位有兩個:Pragma 和 Cache-Control。通過圖片簡單的介紹下一些緩存參數。GRPC( A high-performance, open-source universal RPC framework)不知道各位有沒有聽說過一個都市怪談,字節的網絡庫優化有多厲害多厲害,網絡底層採用的是Webview底層的Chromium的網絡庫,在弱網情況下對於api的優化啥的,巴拉巴拉Cronet是Chromium網絡引擎對不同作業系統做的封裝
  • 最全的Android內存優化技巧
    作者:Geekholt地址:https://www.jianshu.com/p/51e28a2c609c前言在Android中,內存是十分寶貴的資源,內存優化有助於提高用戶的體驗,所以學習內存優化技巧是非常重要的。
  • Android性能優化:手把手帶你全面實現內存優化
    最近有想換工作的同學們,可參考《5月技術崗位內推|RN開發招聘啦》,再往下看,一篇關於性能優化的好文章,很值得去學習。前言在 Android開發中,性能優化策略十分重要本文主要講解性能優化中的內存優化,希望你們會喜歡目錄
  • ​吹爆系列:深入探索 Android 包體積優化
    在本篇文章中,我們主要從以下 七個方面 講解了 Android 包體積優化相關的知識:1)、瘦身優化及 Apk 分析方案:瘦身優勢、APK 組成、APK 分析。2)、代碼瘦身方案探索:Dex 探秘、ProGuard、D8 與 R8 優化、去除 debug 信息與行號信息、Dex 分包優化、使用 XZ Utils 進行 Dex 壓縮、三方庫處理、移除無用代碼、避免產生 Java access 方法、利用 ByteX Gradle  插件平臺中的代碼優化插件。
  • Android性能優化:帶你全面實現內存優化
    常見的內存問題 & 優化方案常見的內存問題如下內存洩露內存抖動圖片Bitmap相關代碼質量 & 數量日常不正確使用下面,我將詳細分析每項的內存問題 & 給出優化方案4.1 內存洩露簡介即 ML
  • Android一些你需要知道的布局優化技巧
    那麼我們優化一下:例子:比如我們請求網絡加載列表,如果網絡異常或者加載失敗我們可以顯示一個提示View,上面可以點擊重新加載。當然一直沒有錯誤時,我們就不顯示。android:divider="@drawable/divider"android:showDividers="middle"其中divider.xml是分隔線樣式。
  • android內存優化總結
    之前做過公司產品的內存優化,不過時間有一段時間了,可能記憶不全,歡迎大家添加補充,有錯誤之處也方便指出。
  • Android性能優化--內存優化
    本文來自Dotry投稿,連結:https://www.jianshu.com/p/38b627adaecd上一篇文章關於Android性能優化--啟動優化探討了啟動優化相關的知識點,在本篇將介紹內存優化的相關優化。
  • 家庭網絡優化升級方案
    大部分家庭網絡都是最簡單的組網,運營商光貓接上路由器就完成了,組網拓撲很簡單,如下圖:理想的「完美」但是實際中要移動路由器的位置需要運營商光貓到路由器之間有網線連接,有的家庭這部分線纜可能已經損壞或者壓根沒有,這種方案可能沒法實施。
  • Android圖片壓縮的幾種方案
    各位同學早上好,今天推薦的是Hensen同學的原創投稿文章,本文將為你介紹Android平臺上幾種壓縮圖片的方案
  • 深信服WOC-2050提出網絡優化解決方案
    如今,網絡已成為企事業單位業務最大的載體,ERP、OA、郵件系統等內部業務系統不僅促進了單位的內部交流,而且承擔著企事業單位大部分的核心業務。銘冠科技總結分布式組織網絡交互、數據集中、移動辦公等問題表現無論是財務系統、業務系統,還是辦公系統,一旦我們離開了單位內網,這些系統資源我們都無法使用。  事實上,現在領導及員工出差、駐外設置分枝機構的現象越來越普遍。
  • Android性能優化典範
    13)Optimizing Your Layout下圖舉例演示了如何優化ListItem的布局,通過RelativeLayout替代舊方案中的嵌套LinearLayout來優化布局代碼的不同寫法會影響到Java編譯器的優化效率。例如for循環的不同寫法就會對編譯器優化這段代碼產生不同的效率,當程序中包含大量這種可優化的代碼的時候,運算性能就會出現問題。想要知道如何優化代碼的運算性能就需要知道代碼在硬體層的執行差異。
  • Android徹底組件化方案實踐
    但是苦於目前還沒有一個完全合適、完美兼容的插件化方案(RePlugin的飢餓營銷做的很好,但還沒看到療效),特別是對於已經有幾十萬代碼量的一個成熟產品來講,套用任何一個插件化方案都是很危險的工作。所以我們決定先從組件化做起,本著做一個最徹底的組件化方案的思路去進行代碼的重構,下面是最近的思考結果,歡迎大家提出建議和意見。
  • Android開發必備的「80」個開源庫
    utm_source=tuicool&utm_medium=referral從零開始的 Android 新項目http://blog.zhaiyifan.cn/2016/03/14/android-new-project-from-0-p1/你需要知道的 Android 拍照適配方案https://www.jianshu.com/p/f269bcda335f
  • 基於PJSIP協議棧和Android的VoIP系統設計方案介紹【詳解】
    本文提出一種基於PJSIP協議棧的解決方案,通過Android本地開發工具(NDK),實現一個高效、穩定且功能強大的VoIP系統,具有較高的參考和實用價值。  1 VoIP設計方案  1.1 設計目標  本方案所設計的系統包含以下功能:首先,完成用戶終端(如手機)中語音數據的採集與編碼,並通過RTP(實時傳輸協議)/RTCP(RTP傳輸控制協議)進行傳輸和控制;其次,完成會話的控制,包括會話的註冊、發起、維護與結束、註銷等;再次,作為一個應用程式,必須實現一個良好的界面,與用戶交互;最後,作為一個開放系統,需具有良好的可擴展性
  • [JAVA] 85天 精通JAVAEE+Android 黑馬程式設計師JavaEE+Android培訓課程60G
    自定義View、自定義窗口標題、自定義Notification、自定義Dialog、各種圖形的使用介紹、meta-data的使用、ListView數據異步加載與AsyncTask、ListView數據的分批加載、拖拉與多點觸摸、Android圖形開發、OpenGl ES、Widget、界面動畫特效、應用調試與Android Junit、使用TraceView進行性能測試、Android應用性能優化方案