Android 网络优化及protobuf

Android 网络优化及protobuf

https是常用的互联网应用层协议,客户端的一次请求大致经历了:客户端获取URL - > DNS解析 - > 建立HTTP连接 - >发送HTTP请求 几个阶段。

可以发现有三个可以优化的地方:

  • 直接使用 IP 地址,去除 DNS 解析步骤;

  • 连接复用;

  • 压缩数据,减小传输的数据大小。

DNS优化

DNS(Domain Name System),它的作用是根据域名查出IP地址,它是HTTP协议的前提,只有将域名正确的解析成IP地址后,后面的HTTP流程才能进行。DNS 完整的解析流程很长,会先从本地系统缓存取,若没有就到最近的 DNS 服务器取,若没有再到主域名服务器取,每一层都有缓存,但为了域名解析的实时性,每一层缓存都有过期时间。

传统的DNS解析机制有几个缺点:

  • 缓存时间设置得长,域名更新不及时,设置得短,大量 DNS 解析请求影响请求速度;
  • 域名劫持,容易被中间人攻击,或被运营商劫持,把域名解析到第三方 IP 地址;
  • DNS 解析过程不受控制,无法保证解析到最快的IP;

针对传统DNS的缺点,HTTPDNS主要有以下优点:

  • 域名防劫持
  • 智能调度(获取最快最优IP)

相关文章推荐 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

腾讯云 https://cloud.tencent.com/product/cns?fromSource=gwzcw.2602306.2602306.2602306&utm_medium=cpc&utm_id=gwzcw.2602306.2602306.2602306#advantage

连接复用

HTTP/2主要是为了解决现HTTP 1.1性能不好的问题才出现的。当初Google为了提高HTTP性能,做出了SPDY,它就是HTTP/2的前身,后来也发展成为HTTP/2的标准。

HTTP/2兼容HTTP 1.1,例如HTTP Method,Status code,URI以及大部分Header Fields。

HTTP/2通过以下方法减少latency,用来改进页面加载的速度,

  1. HTTP Header的压缩,采用的是HPack算法。
  2. HTTP/2的Server Push,非常重要的一个特性。
  3. 请求的pipeline。
  4. 修复在HTTP 1.x的队头阻塞问题。
  5. 在单个TCP连接里多工复用请求。

HTTP/2支持HTTP 1.1里的大部分use case,例如桌面浏览器、移动浏览器、Web API、Web Server、代理服务器、反向代理服务器、防火墙和CDN等。

参考博客 https://www.cnblogs.com/confach/p/10141273.html

简单来说就是客户端和服务端都使用HTTP/2

数据压缩

数据对请求速度的影响分两方面,一是压缩率,二是解压序列化反序列化的速度。目前最流行的两种数据格式是 json 和 protobuf,json 是字符串,protobuf 是二进制,即使用各种压缩算法压缩后,protobuf 仍会比 json 小,数据量上 protobuf 有优势,序列化速度 protobuf 也有一些优势 。

相比其他格式,protobuf优势有如下几点

  1. 序列化后体积相比Json和XML很小,适合网络传输

  2. 支持跨平台多语言

  3. 消息格式升级和兼容性还不错

  4. 序列化反序列化速度很快,快于Json的处理速速
    PS:在一个需要大量的数据传输的场景中,如果数据量很大,那么选择protobuf可以明显的减少数据量,减少网络IO,从而减少网络传输所消耗的时间。

protobuf使用

protobuf GitHub仓库地址 https://github.com/protocolbuffers/protobuf/tree/master/java

  1. 添加gradle插件

    classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.13'
    
  2. 应用插件

    apply plugin: 'com.google.protobuf'
    
    protobuf {
        protoc {
            artifact = 'com.google.protobuf:protoc:3.11.0'
        }
        generateProtoTasks {
            all().each { task ->
                task.builtins {
                    java {
                        option "lite"
                    }
                }
            }
        }
    }
    
  3. 添加依赖

    implementation 'com.google.protobuf:protobuf-javalite:3.11.0'
    
  4. 在java文件夹同级目录下创建proto文件夹,并创建.proto文件


    proto_create.png
  5. 填写.proto 文件内容,参考语法 https://blog.csdn.net/qq_22660775/article/details/89163881

    syntax = "proto3";//proto3
    
    option java_package = "com.example.proto";//生成的java类的包名
    
  6. 编译构建,就会在生成对应的java文件


    proto_build.png
  7. 调用对应的java API

            //构建对象
            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,曾经尝试把protobuf-java-util中的类拷贝下来,但由于util包依赖太多,最终放弃了

    使用fastjson打印结果中数据,虽然内容变多了,但核心内容都在,可以勉强使用。

    {
        "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
    }
    
  1. 推荐Android studio 安装两个插件


    proto_plugin.png
    • protocol-buffer-editor 插件(语法高亮)

    • pojo to proto 插件(拷贝java bean文件,生成proto文件的内容)

pojo_copy.png
pojo_paste.png

其他

  1. 根据网络情况下发图片,在2G/3G/4G/5G/WIFI下分别获取不同分辨率的图片
  2. 开启数据压缩(okhttp默认支持接收gzip压缩)
  3. 根据网络情况下发图片,在2G/3G/4G/5G/WIFI下分别获取不同分辨率的图片
  4. WIFI下,按需提前上传下载大数据包
  5. 使用长连接保活时考虑智能心跳包时间间隔
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容