<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android網(wǎng)絡優(yōu)化攻略,簡單了解一下?

          共 6272字,需瀏覽 13分鐘

           ·

          2021-02-26 18:20

          轉自:掘金 - 究極逮蝦戶

          https://juejin.cn/post/6896302142542315533


          1  如何優(yōu)化一個網(wǎng)絡請求呢?

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


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

          DNS優(yōu)化

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

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


          如果你的網(wǎng)絡層用的是OkHttp的話,Okhttp在封裝的時候就已經(jīng)考慮到這個部分了,其內部提供了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是不可以被信任的,經(jīng)常會有運營商會搞一些奇奇怪怪的Dns攔截,導致大家收到的請求是運營商所緩存的(目的是為了省流量),所以阿里騰訊等都有自己對外輸出的HttpDns的服務。這個服務可以幫助大家找到真實準確的Host的Ip,就是這個服務是收錢的。

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

          https://blog.csdn.net/firefile/article/details/80532161

          CacheControl

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

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

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



          如果說一句不負責任的話,這個只要后端大佬開啟CacheControl就好了呀,原生網(wǎng)絡庫本來就支持的。

          當然后端大佬一般都不是特別愿意,其實各位安卓也可以通過添加OkHttp攔截器的方式給網(wǎng)絡請求添加一個統(tǒng)一的CacheControl,當然如果你有定制化的需求肯定還是要自己開發(fā)的,細節(jié)大家可以參考下這個倉庫:

          https://github.com/yale8848/RetrofitCache

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

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

          Http 1.0 - 1.1 - 1.X - 2.0

          以下所有內容均來自網(wǎng)絡 HTTP1.0、HTTP1.1 和 HTTP2.0 的區(qū)別。

          https://www.cnblogs.com/heluan/p/8620312.html

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

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

          2. header壓縮,如上文中所言,對前面提到過HTTP1.x的header帶有大量信息,而且每次都要重復發(fā)送,HTTP2.0使用encoder來減少需要傳輸?shù)膆eader大小,通訊雙方各自cache一份header fields表,既避免了重復header的傳輸,又減小了需要傳輸?shù)拇笮 ?/p>

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

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

          HTTP2.0的多路復用和HTTP1.X中的長連接復用有什么區(qū)別?

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

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

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

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

          GRPC( A high-performance, open-source universal RPC framework)

          不知道各位有沒有聽說過一個都市怪談,字節(jié)的網(wǎng)絡庫優(yōu)化有多厲害多厲害,網(wǎng)絡底層采用的是Webview底層的Chromium的網(wǎng)絡庫,在弱網(wǎng)情況下對于api的優(yōu)化啥的,巴拉巴拉.....

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

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

          https://github.com/grpc/grpc-java

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

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

          你可以定義數(shù)據(jù)的結構,然后使用特殊生成的源代碼輕松的在各種數(shù)據(jù)流中使用各種語言進行編寫和讀取結構數(shù)據(jù)。你甚至可以更新數(shù)據(jù)結構,而不破壞由舊數(shù)據(jù)結構編譯的已部署程序。

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

          由GRRC升級QUIC

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

          其實整個QUIC協(xié)議(Http3.0協(xié)議)本來就是谷歌寫的,所以谷歌的Cronet本身就支持這也是正常的。

          我其實之前就特地去查過OKHttp支持的協(xié)議內容,當前還是只停留在2.0階段,主要就還是因為當前的Connection寫的太好了,而且需要把Tcp直接更換成Udp,所以遲遲沒有更新3.0協(xié)議的支持。

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

          2 還能干嗎?

          其實優(yōu)化方面我的大概的姿勢點就這么多了,但是我們可以考慮從監(jiān)控方面的角度去再重新審視這個話題哦。


          客戶端請求從發(fā)起到網(wǎng)關實際接收到,其實中間有很復雜的鏈路,簡單的說,OKhttp內也走過了這么多個攔截器了。但是當一個線上用戶反饋這個界面怎么刷出來的這么慢的情況下,我們以后端網(wǎng)關開始作為請求的開始節(jié)點,就會出現(xiàn)難以定位真實問題的情況。

          基于OkHttp的網(wǎng)絡監(jiān)控

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

          參考數(shù)據(jù)深入理解OkHttp3:(七)事件(Events)https://www.pianshen.com/article/8120939/

          基于OKHttp提供的EventListener,我們就可以對于一個請求發(fā)起到最后的各個節(jié)點進行監(jiān)控,之后上報日志數(shù)據(jù),這樣在后續(xù)的撕逼過程中,其實就可以做到有理有據(jù),有話可說,你真的慢了。

          總結

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



          PS:如果覺得我的分享不錯,歡迎大家隨手點贊、在看。

          大家一起在評論區(qū)聊聊唄~

          瀏覽 103
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色视频网站一级片 | 黄色片在线免费观看91 | 成年人激情网 | 黄色视频在线观看日本极品尤物 | 日韩性爱片 |