现代移动端网络短链接的优化手段总结:请求速度、弱网适应、安全保障

一、前言

众所周之,一般咱们开发一个移动端应用,会直接调用系统提供的网络请求接口去服务端请求数据,再针对返回的数据进行一些处理,或者使用iOS中的开源AFNetworking/OKHttp这样的网络库(Android中能够用HttpURLConnection或者开源的okhttp库),管理好请求线程和队列,再自动作一些数据解析,就结束了。html

但对于追求用户体验的应用来讲,还会针对移动网络的特性作进一步优化,包括:前端

1)速度优化:网络请求的速度怎样能进一步提高?git

2)弱网适应:移动端网络环境随时变化,常常出现网络链接很不稳定可用性差的状况,怎样在这种状况下最大限度最快地成功请求?github

3)安全保障:怎样防止被第三方窃听/篡改或冒充,防止运营商劫持,同时又不影响性能?算法

对基于浏览器的前端开发来讲,网络这块能作的事情不多,但对于原生的移动端应用来讲(本文中说的原生主要指iOS和Android应用),整个网络请求过程是自由控制的,能够作不少事情。不少大型 APP 都针对这三个问题作了不少网络层的优化,一些新的网络层协议像 HTTP2 / QUIC 也是在这些方面进行了很多优化。在此请跟着个人文字,边学习边整理,总结一下当今主流的移动端网络短链接常见优化手段,但愿能给您带来启发。编程

本文整理的有关内容,对于移动端即时通信IM应用来讲,一样具备启发意义,由于现今主流的移动端IM数据通讯总结下来无外乎就是长链接+短链接的方式,则短链接的优化在某些场景下对于移动端IM来讲可能显示的更为特出。在这方面,微信作的比较完全和极端,几乎再造了一套针对移动端IM的网络层框架(详见:《如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源》)。json

(本文同步发布于:www.52im.net/thread-1413…浏览器

二、相关文章

1)关于网络通讯的基础文章:缓存

若是您对网络通讯知识了解甚少,建议阅读《网络编程懒人入门系列文章》,更高深的网络通讯文章能够阅读《鲜为人知的网络编程系列文章》。安全

2)涉及移动端网络特性的文章:

谈谈移动端 IM 开发中登陆请求的优化

移动端IM开发须要面对的技术问题(含通讯协议选择)

简述移动端IM开发的那些坑:架构设计、通讯协议和客户端

微信对网络影响的技术试验及分析(论文全文)

腾讯原创分享(一):如何大幅提高移动网络下手机QQ的图片传输速度和成功率

腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(上篇)

腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(下篇)

如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源

三、关于做者

本文原始内容来自JSPatch开源工程做者bang的技术分享,他的博客是:blog.cnbang.net/about/,本次内容有优化和完善,感谢原做者的无私分享。

四、请求速度的优化

正常一条网络请求须要通过的流程是这样:

1)DNS 解析,请求DNS服务器,获取域名对应的 IP 地址;

2)与服务端创建链接,包括 tcp 三次握手,安全协议同步流程;

3)链接创建完成,发送和接收数据,解码数据。

这里有明显的三个优化点:

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

2)不要每次请求都从新创建链接,复用链接或一直使用同一条链接(长链接);

3)压缩数据,减少传输的数据大小。

逐条来看能作什么。

4.1 DNS优化

DNS 完整的解析流程很长,会先从本地系统缓存取,若没有就到最近的 DNS 服务器取,若没有再到主域名服务器取,每一层都有缓存,但为了域名解析的实时性,每一层缓存都有过时时间。

上面这种 DNS 解析机制有几个缺点:

1)缓存时间设置得长,域名更新不及时,设置得短,大量 DNS 解析请求影响请求速度;

2)域名劫持,容易被中间人攻击,或被运营商劫持,把域名解析到第三方 IP 地址,据统计劫持率会达到7%;

3)DNS 解析过程不受控制,没法保证解析到最快的IP;

4)一次请求只能解析一个域名。

为了解决这些问题,就有了 HTTPDNS,原理很简单,就是本身作域名解析的工做,经过 HTTP 请求后台去拿到域名对应的 IP 地址,直接解决上述全部问题。

自已实现HTTPDNS的好处总结就是:

1)域名解析与请求分离,全部请求都直接用IP地址,无需 DNS 解析,APP 定时请求 HTTPDNS 服务器更新IP地址便可;

2)经过签名等方式,保证 HTTPDNS 请求的安全,避免被劫持;

3)DNS 解析由本身控制,能够确保根据用户所在地返回就近的 IP 地址,或根据客户端测速结果使用速度最快的 IP;

4)一次请求能够解析多个域名。

其他细节就很少说了,HTTPDNS 优势这么多,几乎成为中大型 APP 的标配。至此解决了第一个问题 — DNS 解析耗时的问题,顺便把一部分安全问题 — DNS 劫持也解决了。

关于移动端网络中DNS的问题,《谈谈移动端 IM 开发中登陆请求的优化》一文中也有提到,仅供参考。

4.2 链接的优化

第二个问题,链接创建耗时的问题,这里主要的优化思路是复用链接,不用每次请求都从新创建链接,如何更有效率地复用链接,能够说是网络请求速度优化里最主要的点了,而且这里的优化仍在演进过程当中,值得了解下。

▼【keep-alive】:

HTTP 协议里有个 keep-alive,HTTP1.1默认开启,必定程度上缓解了每次请求都要进行TCP三次握手创建链接的耗时。原理是请求完成后不当即释放链接,而是放入链接池中,若这时有另外一个请求要发出,请求的域名和端口是同样的,就直接拿出链接池中的链接进行发送和接收数据,少了创建链接的耗时。

实际上如今不管是客户端仍是浏览器都默认开启了keep-alive,对同个域名不会再有每发一个请求就进行一次建连的状况,纯短链接已经不存在了。但有个问题,就是这个 keep-alive 的链接一次只能发送接收一个请求,在上一个请求处理完成以前,没法接受新的请求。若同时发起多个请求,就有两种状况:

若串行发送请求,能够一直复用一个链接,但速度很慢,每一个请求都要等待上个请求完成再进行发送。

若并行发送这些请求,那么首次每一个请求都要进行tcp三次握手创建新的链接,虽然第二次能够复用链接池里这堆链接,但若链接池里保持的链接过多,对服务端资源产生较大浪费,若限制了保持的链接数,并行请求里超出的链接仍每次要建连。

对这个问题,新一代协议 HTTP2 提出了多路复用去解决。

PS:关于理解TCP的3次握手原理,如下文章可能对您会有帮助

TCP/IP详解 - 第18章·TCP链接的创建与终止

理论经典:TCP协议的3次握手与4次挥手过程详解

理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程

通俗易懂-深刻理解TCP协议(上):理论基础

▼【多路复用】:

HTTP2 的多路复用机制同样是复用链接,但它复用的这条链接支持同时处理多条请求,全部请求均可以并发在这条链接上进行,也就解决了上面说的并发请求须要创建多条链接带来的问题。

网络上有张图能够较形象地表现这个过程:

HTTP1.1的协议里,在一个链接里传送数据都是串行顺序传送的,必须等上一个请求所有处理完后,下一个请求才能进行处理,致使这些请求期间这条链接并非满带宽传输的,即便是HTTP1.1的pipelining能够同时发送多个request,但response还是按请求的顺序串行返回,只要其中一个请求的response稍微大一点或发生错误,就会阻塞住后面的请求。

HTTP2 这里的多路复用协议解决了这些问题,它把在链接里传输的数据都封装成一个个stream,每一个stream都有标识,stream的发送和接收能够是乱序的,不依赖顺序,也就不会有阻塞的问题,接收端能够根据stream的标识去区分属于哪一个请求,再进行数据拼接,获得最终数据。

解释下多路复用这个词,多路能够认为是多个链接,多个操做,复用就是字面上的意思,复用一条链接或一个线程。HTTP2这里是链接的多路复用,网络相关的还有一个I/O的多路复用(select/epoll),指经过事件驱动的方式让多个网络请求返回的数据在同一条线程里完成读写。

移动客户端来讲,iOS 9 以上 NSURLSession 已原生支持 HTTP2,只要服务端也支持就能够直接使用,Android 的开源网络库 okhttp3以上版本也支持了 HTTP2,国内一些大型 APP 会自建网络层,支持 HTTP2 的多路复用,避免系统的限制以及根据自身业务须要增长一些特性,例如微信的开源网络库 mars(详见《如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源》),作到一条长链接处理微信上的大部分请求,多路复用的特性上基本跟 HTTP2 一致。

▼【TCP队头阻塞】:

HTTP2 的多路复用看起来是完美的解决方案,但还有个问题,就是队头阻塞,这是受限于 TCP 协议,TCP 协议为了保证数据的可靠性,若传输过程当中一个 TCP 包丢失,会等待这个包重传后,才会处理后续的包。HTTP2的多路复用让全部请求都在同一条链接进行,中间有一个包丢失,就会阻塞等待重传,全部请求也就被阻塞了。

对于这个问题不改变 TCP 协议就没法优化,但 TCP 协议依赖操做系统实现以及部分硬件的定制,改进缓慢,因而 GOOGLE 提出 QUIC 协议(详见《技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解》),至关于在 UDP 协议之上再定义一套可靠传输协议,解决 TCP 的一些缺陷,包括队头阻塞。具体解决原理网上资料较多,能够看看。

QUIC 处于起步阶段,少有客户端接入,QUIC 协议相对于 HTTP2 最大的优点是对TCP队头阻塞的解决,其余的像安全握手 0RTT / 证书压缩等优化 TLS1.3 已跟进,能够用于 HTTP2,并非独有特性。TCP 队头阻塞在 HTTP2 上对性能的影响有多大,在速度上 QUIC 能带来多大提高待研究(关于这一点能够看看腾讯的QUIC技术实践《让互联网更快:新一代QUIC协议在腾讯的技术实践分享》)。

PS:关于新一代QUIC协议的更多文章请见

技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解

让互联网更快:新一代QUIC协议在腾讯的技术实践分享

七牛云技术分享:使用QUIC协议实现实时视频直播0卡顿!

4.3 数据压缩优化

第三个问题,传输数据大小的问题。数据对请求速度的影响分两方面,一是压缩率,二是解压序列化反序列化的速度。目前最流行的两种数据格式是 json 和 protobuf,json 是字符串,protobuf 是二进制,即便用各类压缩算法压缩后,protobuf 仍会比 json 小,数据量上 protobuf 有优点,序列化速度 protobuf 也有一些优点,这二者的对比就不细说了。(关于protobuf的原理,详见《Protobuf通讯协议详解:代码演示、详细原理介绍等》、《全方位评测:Protobuf性能到底有没有比JSON快5倍?》、《强列建议将Protobuf做为你的即时通信应用数据传输格式》)

压缩算法多种多样,也在不断演进,最新出的 Brotli 和Z-standard实现了更高的压缩率,Z-standard 能够根据业务数据样本训练出适合的字典,进一步提升压缩率,目前压缩率表现最好的算法。

除了传输的 body 数据,每一个请求 HTTP 协议头的数据也是不可忽视,HTTP2 里对 HTTP 协议头也进行了压缩,HTTP 头大可能是重复数据,固定的字段如 method 能够用静态字典,不固定但多个请求重复的字段例如 cookie 用动态字典,能够达到很是高的压缩率,这里有详细介绍《HTTP/2 头部压缩技术介绍》(该做者针对HTTP2有不少研究,更多HTTP2文章可见做者的HTTP2技术专题,方便进行深刻学习)。

经过 HTTPDNS,链接多路复用,更好的数据压缩算法,能够把网络请求的速度优化到较不错的程度了,接下来再看看弱网和安全上能够作的事情。

五、针对移动弱网的优化

手机无线网络环境不稳定,针对弱网的优化,微信有较多实践和分享,包括:

1)提高链接成功率:

复合链接,创建链接时,阶梯式并发链接,其中一条连通后其余链接都关闭。这个方案结合串行和并发的优点,提升弱网下的链接成功率,同时又不会增长服务器资源消耗,见下图

2)制定最合适的超时时间:

对总读写超时(从请求到响应的超时)、首包超时、包包超时(两个数据段之间的超时)时间制定不一样的计算方案,加快对超时的判断,减小等待时间,尽早重试。这里的超时时间还能够根据网络状态动态设定;

3)调优TCP参数,使用TCP优化算法:

对服务端的TCP协议参数进行调优,以及开启各类优化算法,使得适合业务特性和移动端网络环境,包括RTO初始值,混合慢启动,TLP,F-RTO等。

针对弱网的这些细致优化未成为标准,系统网络库没有内置,不过前两个客户端优化微信的开源网络库 mars 有实现,如有须要可使用(详见《如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源》)。

六、安全方面

标准协议 TLS 保证了网络传输的安全,前身是 SSL,不断在演进,目前最新是 TLS1.3。常见的 HTTPS 就是 HTTP 协议加上 TLS 安全协议。

安全协议归纳性地说解决两个问题:

1)保证安全;

2) 下降加密成本。

在保证安全上:

1)使用加密算法组合对传输数据加密,避免被窃听和篡改;

2)认证对方身份,避免被第三方冒充;

3)加密算法保持灵活可更新,防止定死算法被破解后没法更换,禁用已被破解的算法。

下降加密成本上:

1)用对称加密算法加密传输数据,解决非对称加密算法的性能低以及长度限制问题;

2)缓存安全协议握手后的密钥等数据,加快第二次建连的速度;

3)加快握手过程:2RTT-> 0RTT。加快握手的思路,就是本来客户端和服务端须要协商使用什么算法后才能加密发送数据,变成经过内置的公钥和默认的算法,在握手的同时就把数据发出去,也就是不须要等待握手就开始发送数据,达到0RTT。

这些点涉及的细节很是多,对 TLS 的介绍有一篇雄文,说得很详细,在此推荐:《TLS协议分析 与 现代加密通讯协议设计》(JackJiang注:这篇文章长的惊人,但愿你能耐心把它看完 ^_^)。

下面这几篇是有关移动端通讯安全的基础文章,比上面那篇要容易理解:

即时通信安全篇(三):经常使用加解密算法与通信安全讲解

即时通信安全篇(六):非对称加密技术的原理与应用实践

传输层安全协议SSL/TLS的Java平台实现简介和Demo演示

微信新一代通讯安全解决方案:基于TLS1.3的MMTLS详解

来自阿里OpenIM:打造安全可靠即时通信服务的技术实践分享

通俗易懂:一篇掌握即时通信的消息传输安全原理

目前基本主流都支持 TLS1.2,iOS 网络库默认使用 TLS1.2,Android4.4 以上支持 1.2。TLS1.3 iOS 还处于测试阶段,Android 未查到消息。对于普通 APP,只要正确配置证书,TLS1.2 已经能保证传输安全,只是在建连速度上会有所损耗,有一些大型 APP 像微信就自行实现了 TLS1.3 的部分协议,早一步全平台支持(微信团队专门分享过关于TLS1.3的实践文章,详见《微信新一代通讯安全解决方案:基于TLS1.3的MMTLS详解》)。

七、写在最后

移动端网络优化这个话题很是庞大,本文只是在学习过程当中从优化思路上列举了目前业界常见的优化点,还有不少细节不少更深刻的优化没涉及到,网络层实践开发经验不足,如有错误欢迎指出。

(本文同步发布于:www.52im.net/thread-1413…

相关文章
相关标签/搜索