百度APP移动端网络深度优化实践分享二网络连接优化篇

36次阅读

共计 9055 个字符,预计需要花费 23 分钟才能阅读完成。

本文由百度技术团队“蔡锐”原创发表于“百度 App 技术”公众号,原题为《百度 App 网络深度优化系列《二》连接优化》,感谢原作者的无私分享。

一、前言

在《百度 APP 移动端网络深度优化实践分享(一):DNS 优化篇》里大家了解到网络优化一般会首选优化 DNS,而接下来的 HTTP 协议成为优化的重点,一般优化者会选择协议切换,合并请求,精简数据包大小等手段来对 HTTP 协议进行优化,严谨的说这都不属于网络优化的范畴。

HTTP 协议的基础是连接,所以我们的《百度 APP 移动端网络深度优化实践分享(二):网络连接优化篇》应运而生,希望对大家在网络方向的学习和实践有所帮助。

本系列文章目录如下:

《百度 APP 移动端网络深度优化实践分享(一):DNS 优化篇》

《百度 APP 移动端网络深度优化实践分享(二):网络连接优化篇》(* 本文)

《百度 APP 移动端网络深度优化实践分享(三):移动端弱网优化篇》

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

二、相关文章

《TCP/IP 详解 – 第 17 章·TCP:传输控制协议》

《TCP/IP 详解 – 第 18 章·TCP 连接的建立与终止》

《TCP/IP 详解 – 第 21 章·TCP 的超时与重传》

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

《通俗易懂 - 深入理解 TCP 协议(下):RTT、滑动窗口、拥塞处理》

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

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

《移动端 IM 开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”》

《移动端 IM 开发者必读(二):史上最全移动弱网络优化方法总结》

三、技术背景

连接优化需要解决两个核心问题:

1)连接建立耗时较长,导致请求的总时长变长,进而影响用户体验;

2)在多变的网络环境下,连接建立的过程可能会失败,导致成功率下降,进而影响用户体验。

百度 App 承载着亿级流量,对于每一个请求都需要追求耗时短,成功率高的体验。从协议角度出发,如何才能做到这一点呢?首先我们来看下建立连接耗时的原理。


▲ 建立连接耗时的原理

从上图我们能清晰的看出:

1)DNS Query 需要 1 个 RTT(Round-Trip Time,即往返时间),百度 App 都是基于 HTTPDNS 服务的,所以大部分会命中缓存,如果降级走了系统 DNS,也会命中缓存,命中不了的由于是基于 UDP 协议,所以在连接耗时上没有太大的影响,线上的数据也能说明这点;

2)TCP 要经历 SYN,SYN/ACK,ACK 三次握手的 1.5 个 RTT,不过 ACK 和 ClientHello 合并了,所以就是 1 个 RTT;

3)TLS(Transport Layer Security,即传输层安全性协议)需要经过握手和密钥交换 2 个 RTT。

综上所述:DNS、TLS、TCP 握手阶段用了 4 个 RTT 才到了 ApplicationData 阶段,也就是数据开始传输阶段。

通过上面的分析可以总结出,如果我们能尽量的将 TLS 和 TCP 的 RTT 减少,将会大大降低连接耗时的时间。

四、连接优化我们都能做什么?

百度 App 的优化目标分为两类,一类是 TLS 的连接优化,一类是 TCP 的连接优化。

下面,我们将分别介绍基于这两种优化的思路和实践总结。

五、连接优化之“TLS 的连接优化”

TLS 的连接优化,需要服务端和客户端都需要支持,共同完成优化手段,包括 Session Resumption 和 False Start。

5.1 Session Resumption

Session Resumption 中文意思是会话复用,下图讲解了 Session Resumption 的协议原理。


▲ Session Resumption 的协议原理

通过上图可以看出 TLS 密钥协商交换的过程没有了,但具体是如何实现的呢?包含两种方式,一种是 Sesssion Identifier,一种是 Session Ticket。

1)Session Identifier:

Session Identifier 中文为会话标识符,更像我们熟知的 session 的概念。是 TLS 握手中生成的 Session ID。服务端会将 Session ID 保存起来,客户端也会存储 Session ID,在后续的 ClientHello 中带上它,服务端如果能找到匹配的信息,就可以完成一次快速握手。

2)Session Ticket:

Session Identifier 存在一些弊端,比如客户端多次请求如果没有落在同一台机器上就无法找到匹配的信息,但 Session Ticket 可以。Session Ticket 更像我们熟知的 cookie 的概念,Session Ticket 用只有服务端知道的安全密钥加密过的会话信息,保存在客户端上。客户端在 ClientHello 时带上了 Session Ticket,服务器如果能成功解密就可以完成快速握手。

不管是 Session Identifier 还是 Session Ticket 都存在时效性问题,不是永久生效,对于这两种方式大家可以查看参考资料【4】。百度 App 的网络协议层对这两种方式都是支持的,省去了 TLS 握手过程中证书下载,密钥协商交换的环节,节省了 1 个 RTT 的时间。

5.2 False Start

False Start 的中文意思是抢跑,下图讲解了 False Start 的协议原理。


▲ False Start 的协议原理

上图很清晰的说明在 TLS 第一步握手成功后,客户端在发送 Change Cipher Spec Finished 的同时开始数据传输,服务端在 TLS 握手完成时直接返回应用数据。应用数据的发送实际上并未等到握手全部完成,所以称之为抢跑。

从结果看省去了 1 个 RTT 的时间。False Start 有两个前提条件:

一是要通过应用层协议协商 ALPN(Application Layer Protocol Negotiation)握手;

二是要支持前向安全的加密算法。

False Start 在未完成握手的情况下就发送了数据,前向安全可以提高安全性,具体协议实现,大家可以查看参考资料【3】。百度 App 的网络协议层对 False Start 是支持的。

这里说句题外话,其实 TCP 层有个类似的连接优化手段叫 Fast Open,感兴趣的同学,可以查看参考资料【5】。

5.3 Session Resumption 和 False Start 的区别

两者对于 TLS 来说都是节省一个 RTT,Session Resumption 在第一次握手时还是需要 2 个 RTT,在第二次握手时才能复用减少到 1 个 RTT。False Start 是端上的行为,故每次都会减少到 1 个 RTT。

六、连接优化之“TCP 的连接优化”

TCP 的连接优化,我们先从连接池说起,首先让我们来认识下连接池都有哪些类型。

6.1 连接池


▲ 连接池的类型

上图展示了连接池的不同类型,都是大家耳熟能详的协议连接池,有低级连接池,包含 TCP 连接池(管理 HTTP 请求的连接)和 WebSocket 连接池(管理 WebSocket 连接)。

有高级连接池,包括 HTTP 代理连接池(管理 HTTP 代理请求的连接),SpdySession 连接池(管理 SPDY 和 HTTP/ 2 请求的连接),SOCKS 连接池(管理 SOCKS 和 SOCKS5 代理的连接),SSL 连接池(管理 HTTPS 请求的连接)。

不同类型的连接池以组合的形式互相复用能力:

1)SSL 连接池管理的是 SSLSocket,但 SSLSocket 又依赖于 TCP 连接池提供的 TCPSocket;

2)HTTP 代理连接池如果走 HTTP 协议,那么就需要 TCP 连接池提供 TCPSocket,如果走 HTTPS 协议,那么就需要 SSL 连接池提供 SSLSocket;

3)SpdySession 连接池依赖 SSL 连接池提供 SSLSocket,这里需要说明下,虽然 HTTP/ 2 协议没有强制绑定 HTTPS,但是在实际开发中确实都是绑定 HTTPS,百度 App 使用 ALPN 来协商 HTTP/2;

4)SOCKS 连接池管理的 SOCKSSocket 和 SOCKS5Socket 都需要依赖 TCP 连接池提供的 TCPSocket,虽然 SOCKS5 支持 UDP,但 cronet 网络库暂时没有实现;

5)WebSocket 连接池依赖 TCP 连接池提供的 TCPSocket,声明下这里没有说明 WSS(Web Socket Secure)的情况。

TCP 连接优化是一个比较复杂的内容,百度 App 做了针对性场景优化,包括预连接,连接重建,备用连接,复合连接。

6.2 预连接


▲ 预连接和连接重建

预连接:预先创建好的连接。它解决的场景是在 App 使用阶段可以无耗时的获取连接。下面用四个问答来解释预连接。

问题一:预连接是否能解决所有网络请求的提前连接建立?

答:答案是否定的,预连接需要业务方进行核心业务的评估,针对核心的域名进行预连接的建立。

问题二:预连接既然针对的是特定的域名,那么是如何配置的呢?

答:采用域名 + 连接数的方式进行配置,比如 https://a.baidu.com|2,表示给 a.baidu.com 这个域名配置两条预连接,这里要说明下,在 HTTP/1.x 协议下,网络库的实现都会对于单域名有最大连接数的限制,不同网络库的个数限制不一样,有 5 个也有 6 个,但对于 HTTP/ 2 协议,这个连接数就只能是 1 个。

问题三:预连接是如何建立的?

答:在网络库初始化的时候,会根据使用者的配置延迟 5s 进行预连接的建立,主要是考虑网络库在冷启动下对于启动性能的影响,为了保证网络库的整体性能,预连接的总个数限制在 20 个。

问题四:预连接是如何保持的?

答:在网络库初始化的时候,除了进行预连接的建立,还会创建一个预连接的定时器,这个定时器会每隔 31s,这个值的设定取决于 BFE(Baidu Front End,是七层流量的统一接入系统)和 BGW(Baidu Gate Way,百度自主研发的四层负载均衡平台)对超时的最小值设定,根据使用者的配置重新建立连接。

6.3 连接重建

连接重建,将连接重新建立。它解决的场景是 App 网络状态发生变化,IP 地址变化,导致连接不可用。下面用三个问答来解释连接重建。

问题一:连接重建是否针对连接池里的所有连接?

答:答案是肯定的。

问题二:连接重建的过程是什么样的?

答:在网络状态变化的时候,第一步会清除掉连接池里的 idle socket,何为 idle socket?即空闲 socket,对于从未使用过的空闲 socket 超过 60 秒清除,对于使用过的空闲 socket 超过 90 秒清除。第二步重建连接需要等待 200ms,目的是等待 DNS 先重建完成。

问题三:连接重建对于性能有影响吗?

答:出于性能考虑,连接重建的连接个数限制是 100 个。

6.4 备用连接


▲ 备用连接和复合连接

备用连接,预备的连接。它解决的场景是正常发送一个请求当 group 内无连接可用的时候(何为 group?group 是管理 socket 的最小单元,内部包含活跃 socket,空闲 socket,连接任务,等待请求)。下面用三个问答来解释备用连接。

问题一:备用连接是否针对所有请求?

答:答案是肯定的。

问题二:备用连接的过程是什么样的?

答:当有请求来临时,连接池内无连接可用,会启动一个定时器开启备用连接,定时器的间隔时间是 250ms,与主连接进行竞争,如果主连接因为网络抖动或者网络状态不好,导致连接失败,那么备用连接就直接发送请求。如果主连接成功,那么备用连接就被取消掉。

问题三:备用连接的目的是什么?

答:在连接池无连接的情况下,务必是要创建连接的,在主连接之外加一个备用连接,会大大提升创建连接的成功率,从而提升用户体验。

6.5 复合连接

复合连接,即多条连接。它解决的场景是为了多个 IP 地址的连接选取问题。下面用三个问答来解释复合连接。

问题一:复合连接是否针对所有请求?

答:答案是肯定的。复合连接可以全局开关,百度 App 现阶段暂时没有开启复合连接。

问题二:复合连接的过程是什么样的?

答:众所周知域名 DNS 查询一般情况下会返回多个 IP,我们以域名查询返回两个 IP 为例

1)如果结果中存在 IPv6 的地址,那么会优先选用 IPv6 的地址,这个规则 follow HappyEyeBall 机制(可参考系列一对于 HappyEyeBall 的介绍)。

2)接下来这两个 IP 会按照顺序尝试建立连接,如果第一个 IP 返回失败,将立即开始连接第二个 IP。

3)如果第一个 IP 率先成功返回,那么第二个 IP 将被加入连接尝试列表并停止所有尝试连接。

4)如果第一个 IP 失败,会立刻开始第二个 IP 的连接。

5)如果第一个 IP 处于 pending 状态,那么会启动一个定时器,默认延迟 2s 会发起第二个 IP 的连接,如果是多个 IP 将会递归连接,需要特别说明下,不同的网络制式延迟时间会不一样,这样体验也会更好。

问题三:复合连接的目的是什么?

答:复合连接的好处是提供最优的 IP 选取机制,但也会带来服务端的高负载,所以使用的时候需要进行综合评估。

七、连接优化的最佳实践

百度 App 目前客户端网络架构由于历史原因还未统一,不过我们正朝着这个目标努力。

我们的中心思想是以系统网络库的 API 调用接口为中心,上层建立网络门面,供外部便捷调用,底层通过系统机制以 AOP 的方式将 cronet(chromium 的 net 模块)注入进系统网路库,达到双端网络架构统一,能力复用。

下面着重介绍下连接优化在 Android 和 iOS 网络架构中的位置及实践。

7.1 连接优化在 Android 网络架构的位置及实践


▲ 连接优化在 Android 网络架构的位置

百度 App 的 Android 网络流量目前都在 okhttp 之上,上层进行了网络门面的封装,封装内部的实现细节和对外友好的 API,目前我们正在进行重构,默认采用 Android 标准的网络接口 HttpURLConnection,它的底层由系统提供的 okhttp 的实现。

订制方面利用 URL Stream Protocol 机制将 HttpURLConnection 底层网络协议栈接管为 cronet,供各个业务和基础模块使用,连接优化的所有内容在 cronet 网络库内部实现。

7.2 连接优化在 iOS 网络架构的位置及实践


▲ 连接优化在 iOS 网络架构的位置

百度 App 的 iOS 网络流量目前都在 cronet 之上,上层我们使用 iOS 的 URL Loading System 机制将 cronet stack 注入进 URLSession 里,这样我们就可以直接使用 URLSession 的 API 进行网络的操作而且更易于系统维护,在上层封装了网络门面,供各个业务和基础模块使用。

在 cronet 内部实现了预连接(主要针对百度 App 的几个核心域名进行预连和保活),连接重建(针对所有请求),备用连接(针对所有请求),复合连接(iOS 上暂时没有开启),Session Resumption(针对所有请求),False Start(针对所有请求)。

八、实际收益

连接优化的收益主要体现在网络时延和网络成功率上,这两点收益需要结合业务来说,以百度 App Feed 刷新这个典型业务场景为例。

Feed 刷新文本请求网络时延降低 16%,Feed 刷新图片请求网络时延降低 12%,可谓收益相当明显。

成功率方面,Feed 刷新文本请求成功率提升 0.29%,Feed 刷新图片请求成功率提升 0.23%,也是非常不错的收益。

九、本文结语

连接优化是个持续性的话题,没有最优只有更优。上面介绍的百度 App 的一些经验和做法并不见得完美,但我们会继续深入的优化下去,持续提升百度 App 的网络性能。

以上优化由百度 App 团队,内核团队,OP 团队共建完成。最后感谢大家的辛苦阅读,希望对你有所帮助,后面会继续推出 - 百度 App 网络深度优化系列《三》弱网优化,敬请期待。

十、参考资料

[1]https://chromium.googlesource.co … ild_instructions.md

[2] https://chromium.googlesource.co … ild_instructions.md

[3] False Start:https://tools.ietf.org/html/r…

[4] Session Resumption:https://tools.ietf.org/html/r…

[5] TCP Fast Open:https://tools.ietf.org/html/r…

附录:更多网络通信方面的精华文章

《TCP/IP 详解 – 第 11 章·UDP:用户数据报协议》

《TCP/IP 详解 – 第 17 章·TCP:传输控制协议》

《TCP/IP 详解 – 第 18 章·TCP 连接的建立与终止》

《TCP/IP 详解 – 第 21 章·TCP 的超时与重传》

《技术往事:改变世界的 TCP/IP 协议(珍贵多图、手机慎点)》

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

《通俗易懂 - 深入理解 TCP 协议(下):RTT、滑动窗口、拥塞处理》

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

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

《计算机网络通讯协议关系图(中文珍藏版)》

《UDP 中一个包的大小最大能多大?》

《P2P 技术详解(一):NAT 详解——详细原理、P2P 简介》

《P2P 技术详解 (二):P2P 中的 NAT 穿越(打洞) 方案详解》

《P2P 技术详解(三):P2P 技术之 STUN、TURN、ICE 详解》

《通俗易懂:快速理解 P2P 技术中的 NAT 穿透原理》

《高性能网络编程(一):单台服务器并发 TCP 连接数到底可以有多少》

《高性能网络编程(二):上一个 10 年,著名的 C10K 并发连接问题》

《高性能网络编程(三):下一个 10 年,是时候考虑 C10M 并发问题了》

《高性能网络编程(四):从 C10K 到 C10M 高性能网络应用的理论探索》

《高性能网络编程(五):一文读懂高性能网络编程中的 I / O 模型》

《高性能网络编程(六):一文读懂高性能网络编程中的线程模型》

《不为人知的网络编程(一):浅析 TCP 协议中的疑难杂症(上篇)》

《不为人知的网络编程(二):浅析 TCP 协议中的疑难杂症(下篇)》

《不为人知的网络编程(三):关闭 TCP 连接时为什么会 TIME_WAIT、CLOSE_WAIT》

《不为人知的网络编程(四):深入研究分析 TCP 的异常关闭》

《不为人知的网络编程(五):UDP 的连接性和负载均衡》

《不为人知的网络编程(六):深入地理解 UDP 协议并用好它》

《不为人知的网络编程(七):如何让不可靠的 UDP 变的可靠?》

《不为人知的网络编程(八):从数据传输层深度解密 HTTP》

《网络编程懒人入门(一):快速理解网络通信协议(上篇)》

《网络编程懒人入门(二):快速理解网络通信协议(下篇)》

《网络编程懒人入门(三):快速理解 TCP 协议一篇就够》

《网络编程懒人入门(四):快速理解 TCP 和 UDP 的差异》

《网络编程懒人入门(五):快速理解为什么说 UDP 有时比 TCP 更有优势》

《网络编程懒人入门(六):史上最通俗的集线器、交换机、路由器功能原理入门》

《网络编程懒人入门(七):深入浅出,全面理解 HTTP 协议》

《网络编程懒人入门(八):手把手教你写基于 TCP 的 Socket 长连接》

《网络编程懒人入门(九):通俗讲解,有了 IP 地址,为何还要用 MAC 地址?》

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

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

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

《聊聊 iOS 中网络编程长连接的那些事》

《移动端 IM 开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”》

《移动端 IM 开发者必读(二):史上最全移动弱网络优化方法总结》

《IPv6 技术详解:基本概念、应用现状、技术实践(上篇)》

《IPv6 技术详解:基本概念、应用现状、技术实践(下篇)》

《从 HTTP/0.9 到 HTTP/2:一文读懂 HTTP 协议的历史演变和设计思路》

《脑残式网络编程入门(一):跟着动画来学 TCP 三次握手和四次挥手》

《脑残式网络编程入门(二):我们在读写 Socket 时,究竟在读写什么?》

《脑残式网络编程入门(三):HTTP 协议必知必会的一些知识》

《脑残式网络编程入门(四):快速理解 HTTP/ 2 的服务器推送(Server Push)》

《脑残式网络编程入门(五):每天都在用的 Ping 命令,它到底是什么?》

《脑残式网络编程入门(六):什么是公网 IP 和内网 IP?NAT 转换又是什么鬼?》

《以网游服务端的网络接入层设计为例,理解实时通信的技术挑战》

《迈向高阶:优秀 Android 程序员必知必会的网络基础》

《全面了解移动端 DNS 域名劫持等杂症:技术原理、问题根源、解决方案等》

《美图 App 的移动端 DNS 优化实践:HTTPS 请求耗时减小近半》

《Android 程序员必知必会的网络通信传输层协议——UDP 和 TCP》

《IM 开发者的零基础通信技术入门(一):通信交换技术的百年发展史(上)》

《IM 开发者的零基础通信技术入门(二):通信交换技术的百年发展史(下)》

《IM 开发者的零基础通信技术入门(三):国人通信方式的百年变迁》

《IM 开发者的零基础通信技术入门(四):手机的演进,史上最全移动终端发展史》

《IM 开发者的零基础通信技术入门(五):1G 到 5G,30 年移动通信技术演进史》

《IM 开发者的零基础通信技术入门(六):移动终端的接头人——“基站”技术》

《IM 开发者的零基础通信技术入门(七):移动终端的千里马——“电磁波”》

《IM 开发者的零基础通信技术入门(八):零基础,史上最强“天线”原理扫盲》

《IM 开发者的零基础通信技术入门(九):无线通信网络的中枢——“核心网”》

《IM 开发者的零基础通信技术入门(十):零基础,史上最强 5G 技术扫盲》

《IM 开发者的零基础通信技术入门(十一):为什么 WiFi 信号差?一文即懂!》

《IM 开发者的零基础通信技术入门(十二):上网卡顿?网络掉线?一文即懂!》

《IM 开发者的零基础通信技术入门(十三):为什么手机信号差?一文即懂!》

《IM 开发者的零基础通信技术入门(十四):高铁上无线上网有多难?一文即懂!》

《IM 开发者的零基础通信技术入门(十五):理解定位技术,一篇就够》

《百度 APP 移动端网络深度优化实践分享(一):DNS 优化篇》

《百度 APP 移动端网络深度优化实践分享(二):网络连接优化篇》

更多同类文章 ……

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

正文完
 0