Android 網(wǎng)絡(luò)優(yōu)化及protobuf
https是常用的互聯(lián)網(wǎng)應(yīng)用層協(xié)議,客戶端的一次請(qǐng)求大致經(jīng)歷了:客戶端獲取URL - > DNS解析 - > 建立HTTP連接 - >發(fā)送HTTP請(qǐng)求 幾個(gè)階段。
可以發(fā)現(xiàn)有三個(gè)可以優(yōu)化的地方:
直接使用 IP 地址,去除 DNS 解析步驟;
連接復(fù)用;
壓縮數(shù)據(jù),減小傳輸?shù)臄?shù)據(jù)大小。
DNS優(yōu)化
DNS(Domain Name System),它的作用是根據(jù)域名查出IP地址,它是HTTP協(xié)議的前提,只有將域名正確的解析成IP地址后,后面的HTTP流程才能進(jìn)行。DNS 完整的解析流程很長,會(huì)先從本地系統(tǒng)緩存取,若沒有就到最近的 DNS 服務(wù)器取,若沒有再到主域名服務(wù)器取,每一層都有緩存,但為了域名解析的實(shí)時(shí)性,每一層緩存都有過期時(shí)間。
傳統(tǒng)的DNS解析機(jī)制有幾個(gè)缺點(diǎn):
- 緩存時(shí)間設(shè)置得長,域名更新不及時(shí),設(shè)置得短,大量 DNS 解析請(qǐng)求影響請(qǐng)求速度;
- 域名劫持,容易被中間人攻擊,或被運(yùn)營商劫持,把域名解析到第三方 IP 地址;
- DNS 解析過程不受控制,無法保證解析到最快的IP;
針對(duì)傳統(tǒng)DNS的缺點(diǎn),HTTPDNS主要有以下優(yōu)點(diǎn):
- 域名防劫持
- 智能調(diào)度(獲取最快最優(yōu)IP)
相關(guān)文章推薦 https://mp.weixin.qq.com/s/iaPtSF-twWz-AN66UJUBDg
百度、阿里、騰訊都推出了自己的HTTPDNS方案。
百度云 https://cloud.baidu.com/doc/HTTPDNS/s/ujwvxm073
阿里云 https://help.aliyun.com/document_detail/30103.html?spm=a2c4g.11186623.6.543.665c3eabM102wL
連接復(fù)用
HTTP/2主要是為了解決現(xiàn)HTTP 1.1性能不好的問題才出現(xiàn)的。當(dāng)初Google為了提高HTTP性能,做出了SPDY,它就是HTTP/2的前身,后來也發(fā)展成為HTTP/2的標(biāo)準(zhǔn)。
HTTP/2兼容HTTP 1.1,例如HTTP Method,Status code,URI以及大部分Header Fields。
HTTP/2通過以下方法減少latency,用來改進(jìn)頁面加載的速度,
- HTTP Header的壓縮,采用的是HPack算法。
- HTTP/2的Server Push,非常重要的一個(gè)特性。
- 請(qǐng)求的pipeline。
- 修復(fù)在HTTP 1.x的隊(duì)頭阻塞問題。
- 在單個(gè)TCP連接里多工復(fù)用請(qǐng)求。
HTTP/2支持HTTP 1.1里的大部分use case,例如桌面瀏覽器、移動(dòng)瀏覽器、Web API、Web Server、代理服務(wù)器、反向代理服務(wù)器、防火墻和CDN等。
參考博客 https://www.cnblogs.com/confach/p/10141273.html
簡單來說就是客戶端和服務(wù)端都使用HTTP/2
數(shù)據(jù)壓縮
數(shù)據(jù)對(duì)請(qǐng)求速度的影響分兩方面,一是壓縮率,二是解壓序列化反序列化的速度。目前最流行的兩種數(shù)據(jù)格式是 json 和 protobuf,json 是字符串,protobuf 是二進(jìn)制,即使用各種壓縮算法壓縮后,protobuf 仍會(huì)比 json 小,數(shù)據(jù)量上 protobuf 有優(yōu)勢,序列化速度 protobuf 也有一些優(yōu)勢 。
相比其他格式,protobuf優(yōu)勢有如下幾點(diǎn)
序列化后體積相比Json和XML很小,適合網(wǎng)絡(luò)傳輸
支持跨平臺(tái)多語言
消息格式升級(jí)和兼容性還不錯(cuò)
序列化反序列化速度很快,快于Json的處理速速
PS:在一個(gè)需要大量的數(shù)據(jù)傳輸?shù)膱鼍爸?,如果?shù)據(jù)量很大,那么選擇protobuf可以明顯的減少數(shù)據(jù)量,減少網(wǎng)絡(luò)IO,從而減少網(wǎng)絡(luò)傳輸所消耗的時(shí)間。
protobuf使用
protobuf GitHub倉庫地址 https://github.com/protocolbuffers/protobuf/tree/master/java
-
添加gradle插件
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.13' -
應(yīng)用插件
apply plugin: 'com.google.protobuf' protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.11.0' } generateProtoTasks { all().each { task -> task.builtins { java { option "lite" } } } } } -
添加依賴
implementation 'com.google.protobuf:protobuf-javalite:3.11.0' -
在java文件夾同級(jí)目錄下創(chuàng)建proto文件夾,并創(chuàng)建.proto文件
proto_create.png -
填寫.proto 文件內(nèi)容,參考語法 https://blog.csdn.net/qq_22660775/article/details/89163881
syntax = "proto3";//proto3 option java_package = "com.example.proto";//生成的java類的包名 -
編譯構(gòu)建,就會(huì)在生成對(duì)應(yīng)的java文件
proto_build.png -
調(diào)用對(duì)應(yīng)的java API
//構(gòu)建對(duì)象 Demo2.Test test = Demo2.Test.newBuilder() .setCode("co") .setNumber(24) .setD(2.22) .setF(1.5f) .addList("sd") .putMap(15,"map12") .build(); //序列化后的長度 int size = test.getSerializedSize(); //序列化 byte[] bytes2 = test.toByteArray(); //反序列化 try { Demo2.Test demoTest2 = Demo2.Test.parseFrom(bytes2); //javalite版無法使用JsonFormat // JsonFormat.printer().print((MessageOrBuilder)demoTest2); //使用fastjson Log.d("protoString", JSON.toJSONString(demoTest2)); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); }比較遺憾的是javalite版無法使用JsonFormat,曾經(jīng)嘗試把protobuf-java-util中的類拷貝下來,但由于util包依賴太多,最終放棄了
使用fastjson打印結(jié)果中數(shù)據(jù),雖然內(nèi)容變多了,但核心內(nèi)容都在,可以勉強(qiáng)使用。
{ "code": "co", "codeBytes": { "empty": false, "validUtf8": true }, "d": 2.22, "defaultInstanceForType": { "code": "", "codeBytes": { "empty": true, "validUtf8": true }, "d": 0, "defaultInstanceForType": { "$ref": "@" }, "f": 0, "initialized": true, "listCount": 0, "listList": [], "map": {}, "mapCount": 0, "mapMap": {}, "number": 0, "parserForType": {}, "serializedSize": 0 }, "f": 1.5, "initialized": true, "listCount": 1, "listList": [ "sd" ], "map": { "15": "map12" }, "mapCount": 1, "mapMap": { "15": "map12" }, "number": 24, "parserForType": { "$ref": "$.defaultInstanceForType.parserForType" }, "serializedSize": 35 }
-
推薦Android studio 安裝兩個(gè)插件
proto_plugin.pngprotocol-buffer-editor 插件(語法高亮)
pojo to proto 插件(拷貝java bean文件,生成proto文件的內(nèi)容)


其他
- 根據(jù)網(wǎng)絡(luò)情況下發(fā)圖片,在2G/3G/4G/5G/WIFI下分別獲取不同分辨率的圖片
- 開啟數(shù)據(jù)壓縮(okhttp默認(rèn)支持接收gzip壓縮)
- 根據(jù)網(wǎng)絡(luò)情況下發(fā)圖片,在2G/3G/4G/5G/WIFI下分別獲取不同分辨率的圖片
- WIFI下,按需提前上傳下載大數(shù)據(jù)包
- 使用長連接?;顣r(shí)考慮智能心跳包時(shí)間間隔


