如果你的 App,在不需要任何修改的情况下就能提升 15% 以上的访问速度。特别是弱网络的时候能够提升 20% 以上的访问速度。
如果你的 App,在频繁切换 4G 和 WIFI 网络的情况下,不会断线,不需要重连,用户无任何感知。如果你的 App,既需要 TLS 的安全,也想实现多路复用的强大。
如果你刚刚才听说 HTTP2 是下一代互联网协议,如果你刚刚才关注到 TLS1.3 是一个革命性具有里程碑意义的协议,但是这两个协议却一直在被另一个更新兴的协议所影响和挑战。
如果这个新兴的协议,它的名字就叫做“快”,并且正在标准化为新一代的互联网传输协议。
你愿意花一点点时间了解这个协议吗?你愿意投入精力去研究这个协议吗?你愿意全力推动业务来使用这个协议吗?
QUIC 在腾讯的实践
腾讯安全云网关 (STGW) 和腾讯云负载均衡器(Cloud Load Balance)在 2017 年 7 月份就已经在服务端上支持了 Quic 协议,在工程实现上也有很多优化点,同时在生产环境中也取得了较好的效果。相比现在几个开源的方案,STGW 的实现主要有如下几个优点:
- 复用 Nginx 全异步事件驱动框架。
- 私钥代理计算集群加速签名计算。
- 全局缓存提速,减少计算量的同时,提升访问速度。
2.强大的功能。
-
- 支持 Nginx 现有全部模块指令,丰富的第三方模块。
- 复用 Nginx 模块框架,非常灵活地新增第三方功能。
3.稳定性。
-
- 代码完全自主可控。
- 正在经受腾讯亿万级并发流量的考验。
同时我们也在腾讯很多业务包括 QQ 空间、WEB 游戏页面、腾讯云 CLB 上灰度支持了 QUIC 协议。详细的收益数据可以参考第 6 章。
QUIC 线下测试方案
在决定使用 QUIC 协议之前,我们需要对 QUIC 协议的特性及性能做一个全面的测试,如何测试呢?这里简单说一下测试方案。
需要特别说明的测试是在 2016 年底进行的,目前所有域名已经失效,无法再进行测试。
页面构造
根据 http://httparchive.org 的统计,构造了如下页面:
测试环境
手机:华为 mate9
User-Agent:MHA-AL00 Build/HUAWEIMHA-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36
操作系统:Android 7.0
服务端 QUIC 程序:caddy 0.9.4
网站和客户端分布如下:
QUIC 测试框架
- ①表示客户端主动发起的用户请求。
- ②表示从 html 里发出的资源请求。
- ③表示数据上报请求。
测试流程
整个测试流程通过 python 脚本和 adb shell 工具自动化进行。其中移动端和 PC 端的控制流程有所区别。分别简介如下:
移动端测试流程
准备事项:
自动化测试流程如下:
PC 端流程
PC 端不需要 adb,使用 webbrowser 模块控制 chrome 完成即可。
测试结论
由于公司内网的 WIFI 环境不稳定,多次测试发现数据跳动较大,4G 环境下的数据更加稳定可靠,所以主要结论参考 4G 网络下的数据。
QUIC 的优势非常明显,即使在元素比较少(12 个元素)的情况下,相比 HTTP 也能提升 9%,相比 HTTP2 提升 42%,相比 HTTPS 提升 52%。
在页面元素增多的情况下,QUIC 的优势就更加明显,相比 HTTP 提升 36%,相比 HTTP2 提升 47%,相比 HTTPS 提升 64%。
QUIC 性能优化
QUIC 的特性虽然比较先进,但是实现起来却非常复杂,在工程实现方面也有很多优化的空间。比如如何提升 0RTT 成功率,减少服务端的 CPU 消耗量,实现连接迁移和动态的拥塞控制算法等。
提升 0RTT 成功率
安全传输层虽然能够实现 0RTT,优势非常明显。但问题是,不是每一次连接都能实现 0RTT,对于我们的客户端和服务端来讲,如何最大程度地提升 0RTT 的成功率?
0RTT 能实现的关键是 ServerConfig。就像 TLS session resume 实现的关键是 session id 或者 session ticket 一样。
ServerConfig 到达服务端后,我们根据 ServerConfig ID 查找本地内存,如果找到了,即认为这个数据是可信的,能够完成 0RTT 握手。
但是会有两个问题:
明确了问题,那工程层面就需要实现多进程共享及分布式多集群的 ID 共享。
SeverConfig Cache 集群
Stgw 在生成 ServerConfig ID 和内容时,会存储到全局的 Cache 集群。用户握手请求落到任意一台 STGW 机器,从全局 Cache 集群都能找到相应的内容,实现 0RTT 握手。
加密性能的优化
签名计算
QUIC 实现 0RTT 的前提是 ServerConfig 这个内容签名和校验都没有问题。由于 ServerConfig 涉及到 RSA 签名或者 ECDSA 签名,非常消耗我们的 CPU 资源。根据之前的测试数据,RSA 私钥签名计算会降低 90% 的性能。
那如何优化呢?使用 RSA 或者 ECDSA 异步代理计算。核心思路也是三点:
架构如下图所示:
签名代理计算
对称加密的优化
相比非对称密钥交换算法来讲,对称加密算法的性能非常卓越(好 1 到 2 个数量级),但是如果应用层传输内容较大的话,特别是移动端的 CPU 计算能力较弱,对称加密算法对性能的影响也不容忽视。
表格 1 常用对称加密算法性能比较
如何优化呢?通过异步代理的方式显然不可能。原因是:
会极大降低用户访问速度。由于应用层的每一个字节都需要对称加解密,使用异步的方式实现会严重降低加解密的实时性。
那有没有同步的优化方式呢?有。类似 SSL 硬件加速卡,intel 针对 AES 算法实现硬件加速,并将它集成到了 CPU 指令里。
AES-NI 指令
AES-NI 是 intel 推出的针对 AES 对称加密算法进行优化的一系列指令,通过硬件计算实现计算速度的提升。
如何测试 AES-NI 的性能呢?
通过环境变量
aes-ni: OPENSSL_ia32cap="~0x200000200000000" openssl speed -elapsed -evp aes-128-gcm 或者在代码里将 crypto/evp/e_aes.c # define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1