QUIC/HTTP3 协议简析
从 HTTP 的进化历史讲起,细说使用协议的变迁,理解起因发现问题,解码 QUIC 在 HTTP3 中的支撑作用,共同讨论 HTTP3 的未来。
HTTP、HTTP2 和 HTTP3
先和大家来回顾一下 HTTP 的历史,看看 HTTP3 相比 HTTP、HTTP2 都有哪些改进和更新的地方。
HTTP VS HTTP2
HTTP 和 HTTP2 的差别
多路复用:多路复用时,多文件传输有时只要维护一个 TCP 连接。假如是 HTTP1 协议下,每份资源的传输对应一个 TCP 连接,一般最多只能开启 6 个 TCP 连接来传输多路数据,后续每添加一个新链接就会由于拥堵问题卡死,进而导致整个进程无法运行。因而HTTP/2处理了 HTTP 的队头阻塞问题。
头部压缩和 Server Push:HTTP2 会通过 HPACK 做头部压缩。同时 HTTP2 是二进制协议,在解析上相比基于文本的 HTTP解析效率上有所提升,并且 HTTP2 还添加了 Server Push。
在 TCP 下,仍然无法处理推迟问题,比方为防止初始阻塞而引入的慢启动;TCP 队头阻塞,比方因为发生丢包,整个连接涉及的传输数据都需要重传而引起的阻塞。
虽然 HTTP2 相比 HTTP 已经有了改进的地方,但是假如你有 2% 的丢包率,那 HTTP2 在性能上就没有优势了。
上图是造成 TCP 队头拥塞(Head of line blocking)的起因。HTTP2 协议是基于 TCP 的,但是 TCP 本身是无法处理队头拥塞,为什么呢?由于 HTTP2 会把一次传输所有的文件都放在一个 TCP 连接中,只需这个 TCP 中发生一个丢包,连接就必需重新建立,之前所有传输内容进行必需重传,从而造成拥塞。
HTTP3 VS HTTP2
HTTP3 本质不是对 HTTP 协议本身的改进,它主要是集中在如何提高传输效率。上图是相比 HTTP2 而言 HTTP3 提升的点:
HTTP3 使用 stream 进一步扩展了 HTTP2 的多路复用。在 HTTP3 模式下,一般传输多少个文件就会产生对应数量的 stream。当这些文件中的其中一个发生丢包时,你只要要重传丢包文件的对应 stream 就可。
HTTP3 不再是基于 TCP 建立的,而是通过 UDP 建立,在客户空间保证传输的可靠性,相比 TCP,UDP 之上的 QUIC 协议提高了连接建立的速度,降低了推迟。
通过引入 Connection ID,使得 HTTP3 支持连接迁移以及 NAT 的重绑定。
HTTP3 含有一个包括验证、加密、数据及负载的 built-in 的TLS安全机制。
拥塞控制。TCP 是在内核区实现的,而 HTTP3 将拥塞控制移出了内核,通过客户空间来实现。这样做的好处就是不再需要等待内核升级可以实现很方便的进行快速迭代。
头部压缩。HTTP2 使用的 HPACK,HTTP3 更换成了兼容 HPACK 的 QPACK 压缩方案。QPACK 优化了对乱序发送的支持,也优化了压缩率。
为什么选择 QUIC
从图上可以看到 QUIC 协议层就实现了可靠的数据传输,拥塞控制,加密,多路数据流。
至于 QUIC 为什么使用了 UDP 的问题,在理解这个之前,我们需要先知道一个事情。频繁的客户态和核心态切换会效率问题。理论上说,将应用层的东西迁移到内核从而提升效率是可行的,但是这么做会影响操作系统的稳固性。另一方面,我们可以选择将这部分内容迁移到客户空间。比方目前流行的 DPDK,当网卡将数据包传输过来时,它是绕过内核在客户空间进行控制和应用。目前又拍云的 DNS 就进行了这样的解决,让又拍云的整体效率提升了5-10 倍。
接下来我们来正式说一下 QUIC 为什么使用了 UDP 的问题,是由于以下几点:
避免 ossification(僵化):QUIC 协议加密负载,也是避免协议僵化一种方式,比方当中间层解决 UDP 数据时,只要要按照数据包的方式去解决就可,不需要去关注内部层的具体信息。
放弃改进 TCP 本身
创新方向:QUIC 是由谷歌提出的,所以 UDP 是以浏览器为出发点,从协议、从浏览器方向来进行创新。
TLS 1.3 Vs TLS 1.2
TLS 1.3 跟 1.2 的少量提升主要有上图几点,大家可以大致看一下:
TLS 1.3 采用了新的加密套件
TLS 1.3 定义了少量新的证书类型以及秘钥交换机制。在 TLS 1.3 你不再需要去特别指定,它可以根据秘钥套件配件进行证书类型的自主推导。
QUIC 存在的问题
接下来说一下 QUIC 目前存在的问题。
首先是由于这些年性能的优化提升都针对 TCP ,使得 UDP 性能没有任何改进。当然随着 QUIC3 的发布,相信后续应该会有相对的投入。
其次是安全问题,也就是反射攻击,即伪造原地址。这个指发送数据包时的原地址是伪造的,不是真正的地址,会引起放大攻击。起因是 QUIC 握手过程是不对称的,特别是第一次请求时,用户端只要要发送几个字节的信息到服务器,而服务器则需要把证书等很多东西返还给用户端,这个不对称的机会造成了放大。草案 27 定义了两个规则和机制来限制反射攻击:用户端发送Initial包,即第一个数据包时,其长度必需在 1200 bytes以上,不足部分用 Padding 帧填充,同时,当服务端不确定用户端可靠性时,可以发送 Retry 包要求用户端再次提供验证信息。
开源 QUIC 的实现
接下来我们简单说一下目前开源的使用情况:
quiche:这个是用 Rust 做的库,通过 Nginx 调用。google 自己的库也叫 quiche,C++写的。
ATS:Apache Traffic Server
golang:Caddy;
python+C,aioquic
微软msquic
开源 QUIC 的实现有很多,上面只是其中的一部分,同时我选择了quiche 和 aioquic 做了少量简单测试。
上图展现的是从 cloudflare 提供支持 HTTP3 的 curl ,可以看到这个返回的值就是 HTTP/3 200。其中 alternative service 段,指示为 h3—27,表示支持 http3 draft-27 的服务跑在 UDP 443 端口。这个 alt-svc 是 HTTP2 时代就存在,在 HTTP3 也持续使用,由于有些时候浏览器并不知道服务器能否支持 QUIC,所以通过 TCP 发起请求,确定有 H3 支持后,再通过 UDP连接。
这个是 HTTP2 的,目前可能是由于本身库的问题,使用 curl 打不开谷歌,但是从信息上可以看到 27、25 这些都是支持的。
如何部署以及达成 HTTP3 的 QUIC 实现
目前主要有两种方式来实现,一种是代理商,第二种是通过 Nginx。
腾讯是通过整合到 Nginx 利用它来实现框架的。同时由于 QUIC 每一条请求的含有头的数据都会经过加密,腾讯有一个单独的硬件加密群,假如你使用腾讯,那么你所有的加解密都会通过他们的硬件来加速。
从腾讯这个可以看出加解密部分有着很可观的 CPU 占用率,假如后续所有的请求都是通过 HTTP3 来进行的话,在提升这块占用率上需要未雨绸缪。当然就像前面提到的 DPDK,也就是把数据丢到 FPGA 内去加解密是一个可以考虑的处理方案。
通过代理商来实现的这种方式,目前官方暂时还没有消息。我可以像 cloudflare 那样,先在外面进行整合,而后再讲整合链接转到 Nginx 内。
又拍云目前有 LBS 和 Marco ,这个是由于 LBS 只认 TCP/UDP,它看不到 HTTP。也就是我们做了一个负载均衡的集群,通过这个集群在转到 Nginx 上。而使用 UDP 则相当于已经走过了一个四层的负载均衡,那么后续可以尝试将 QUIC 的基线提取出来使用,在代理商上做加解密,从而提高效率。
往期技术文章都在微信同步分享,可以增加微信:upyun0001.png
推荐阅读
容器化技术在数据中心的实践
从新冠疫情出发,漫谈 Gossip 协议
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » QUIC/HTTP3 协议简析