面试官:小萧啊,我好想你啊,你都好久没来找我面试了呀。

小萧:emmmmmmm,这不是怕被你打击吗。

面试官:ok,看来是有备而来,那么我们今天聊聊网络优化咋做吧。

小萧:我大意了,没有闪。老头子,你不讲武德,我奉劝你耗子尾汁。

如何优化一个网络请求呢?

相信大家在面试的时候可能会被问到这个问题。今天我其实就是讲述下我知道的一些简单的优化方式,可以帮助大家在面试的过程中得到点基础分数。

我们先从最简单,大家比较容易了解到的讲起。

DNS优化

DNS则是典型的应用层的协议了,至于说为什么第二层能查第三层的IP,因为DNS是Domain Name System缩写,所以你认为是服务是协1653议都可以。

一个Http请求在建立Tcp连接的过程中,肯定会产生一次DNS,那么我们是不是可以通过内存缓存的方式,通过一个HashMap持有这个HostIP,当下次发起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,就是这个服务是收钱的。

CacheControl

Http请求在1.1阶段就引入了CacheControl了,通过CacheControl可以让后端直接控制请求内容的缓存策略。所以还有比缓存更简单粗暴的网络优化方式吗?

在http中,控制缓存开关的字段有两个:PragmaCache-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 的区别

当然我们还可以让后端升级接口协议版本,这个可以明显提升你请求响应性能。

  1. 长连接,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。

  2. header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。

  3. 新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。

  4. 多路复用(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网络优化的一些简单的总结吧。其实中间能展开的内容也还是有的,就是需要各位自己去摸一摸了。

面试一些复习方案

1、确定好方向,梳理成长路线图

不用多说,相信大家都有一个共识:无论什么行业,最牛逼的人肯定是站在金字塔端的人。所以,想做一个牛逼的程序员,那么就要让自己站的更高,成为技术大牛并不是一朝一夕的事情,需要时间的沉淀和技术的积累。

关于这一点,在我当时确立好Android方向时,就已经开始梳理自己的成长路线了,包括技术要怎么系统地去学习,都列得非常详细。

知识梳理完之后,就需要进行查漏补缺,所以针对这些知识点,我手头上也准备了不少的电子书和笔记,这些笔记将各个知识点进行了完美的总结。

2、通过源码来系统性地学习

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

3、刷题备战,直通大厂

包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

文末

欢迎关注我的CSDN,分享Android干货,交流Android技术。
对文章有何见解,或者有何技术问题,都可以在评论区一起留言讨论,我会虔诚为你解答。
最后,如果你想知道更多Android的知识或需要其他资料我这里均免费分享,只需你多多支持我即可哦!

——可以直接点这里可以看到全部资料内容免费打包领取。

Android:面试官死亡问答,如何优化一个网络请求?大牛多个网络优化方案帮你解决!相关推荐

  1. 【华为笔试】安排面试官。有M个面试官,每个面试官熟悉的编程语言是一个列表,有N个面试者,按照面试者的机试选择的语言分配面试官进行面试(Python)

    题目 有M个面试官,每个面试官熟悉的编程语言是一个列表,比如["Java", "C++", "Golang"]表示该面试官熟悉Java.C+ ...

  2. 对K个不同字符的全排列组成的数组, 面试官从中随机拿走了一个, 剩下的数组作为输入, 请帮忙找出这个被拿走的字符串?

    对K个不同字符的全排列组成的数组, 面试官从中随机拿走了一个, 剩下的数组作为输入, 请帮忙找出这个被拿走的字符串? 比如["ABC", "ACB", &quo ...

  3. 如何独立开发一个网络请求框架

    (原创出处为本博客:http://www.cnblogs.com/linguanh/) 目录:   前言 准备工作  开发模式 开发原则 线程 高并发 TCP/UDP 本类介绍  开发选择 功能列表 ...

  4. Kotlin使用Coroutine+ViewModel+retrofit构建一个网络请求框架

    Kotlin使用Coroutine+ViewModel+retrofit构建一个网络请求框架 公司里的老代码用的网络请求框架技术都比较老,为了快速搭建一个网络请求框架,提高工作效率,记录一下用jetp ...

  5. Android 微博实时热点获取(GET)网络请求

    Android 微博实时热点获取(GET)网络请求 首先在xml文件上界面布局 这边采用LinearLayour布局,首先添加TextView控件来显示标题,第二采用RecyclerView列表控件来 ...

  6. 04、用浏览器显示一个网页时,是否只发了一个网络请求给服务器?

    目录 服务器 思考 服务器 用户量.数据访问量越大,对服务器的性能要求越高 当我们在浏览器上输入网址的时候,比如baidu.com,那就会发送请求给这个服务器,如果同时有一亿个用户在浏览器输入百度网址 ...

  7. 那些年Android面试官常问的知识点,分享一点面试小经验

    开头 年前面试了一些公司,目前已经拿到了阿里跟头条的 offer.去年我也出去找工作了,面试五家拿到了四家公司的 offer.所以在面试方面我应该可以提供一些愚见吧.本篇会讲解一些常见题目以及一些答题 ...

  8. 已经成功拿到了几个offer的我来告诉你,Android面试官问的一些问题,看完这一篇就没有拿不到的offer

    前言 我是2020年毕业于中南大学的计算机学院的,大家可以叫我小吴,我嘞毕业之后在华为实习了差不多一年多,一直都从事着Android开发. 然后2021年的时候因为我自己的一些原因打算离职到外面看看, ...

  9. 安卓开发者中心!那些BAT大厂的Android面试官到底在想些什么?持续更新中

    最近很多人说,Android越来越不好找工作了,学习NDK开发会不会好点,今天就聊聊这个问题.是否应该选择学NDK? 1.哪些场景下要用到NDK开发? 跨平台的库,如FFmpeg, skip,weex ...

最新文章

  1. LeetCode: Search a 2D Matrix
  2. Android Editext监听光标位置
  3. Handler 系列二:如何通信
  4. Dora.Interception,为.NET Core度身打造的AOP框架 [5]:轻松地实现与其他AOP框架的整合...
  5. Solr集群系统架构
  6. hyperion高光谱参数_[ENVI] 珠海一号高光谱数据处理
  7. JS面向对象(二)——构造函数的继承
  8. keepalived高可用lvs集群,主/备和主/主模型
  9. 小白想了解C语言?这一篇就够了hh!
  10. 苹果公布了一些最新无人车进展,但,研发依然缓慢
  11. sudo执行脚本找不到环境变量
  12. 小程序wx.showActionSheet 调起转发、分享
  13. 复变函数 —— 4. 什么是调和函数
  14. 移动云迁移工具:物理服务器迁移到移动云
  15. 应届生面试该注意的小技巧
  16. vue 引入富文本编辑器(巨简单)
  17. OpenGL - Deferred Rendering
  18. 华为交换机查看网口光功率命令
  19. 记录一下ubuntu16.04重新安装系统遇到的问题(重装系列文章一:重装单独ubuntu系统或者win10+ubuntu18双系统)
  20. STM32F103代码远程升级(五)基于MQTT协议WiFi远程升级代码的实现

热门文章

  1. oracle误删表空间 无法关闭,oracle 误删表空间文件启动不了数据库的解决办法
  2. sql 增加自增列 耗时长_SQLServer为已有数据的表添加一个自增列
  3. html盒子阴影的语法,css3 盒阴影box-shadow
  4. 记录一下python绘制地图
  5. 华为麒麟810芯片鸿蒙,华为自研麒麟810实体芯片首曝光 传说中的“鸿蒙”要来了?...
  6. abaqus分析用户手册单元卷_作用卷、分析卷、材料卷三件套,让你也能熟练应用Abaqus...
  7. Intellij IDEA 中无法下载 Cloud Toolkit 问题解决
  8. 一. synchronized 的局限性 与 Lock 的优点
  9. Web测试实践-任务进度-Day02
  10. 自学篇之--js 提取复选框和单选框的值 和纯css的3D按钮