Quiche HTTP/3 协议尝鲜

经验 暂无评论

HTTP/3 协议发布后, cloudflare 发布了新的协议的服务器补丁,在此进行尝鲜。

以下引用自之前的文章 Linux 运维手册之 HTTP 服务

在说 HTTP/3 之前先说一说 HTTP/2 的不足,每次版本更新都是为了解决前一代存在的问题,或者扩充其特性,由于 HTTP/2 及之前的协议都是基于 OSI 七层模型中第四层传输层协议 TCP 协议实现的。因此 TCP 协议存在的问题在 HTTP/2 中也都存在。

小贴士:此处提到了 OSI 七层模型,这七层分别为:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

具体的请看下图:

在日常使用中,一般不使用七层模型,都将其简化为五层模型,将类似的或者不重要的层合并,于是产生了下图:

HTTP/2 的缺点主要有如下两点:

  • TCP 连接时的握手延迟较大,HTTPS 中 TLS 证书交换和 TLS 建立的延时。
  • TCP 的队头阻塞问题依然存在。

小贴士:为什么是三次握手?因为三次握手是建立可靠连接(双向确认)所需的最少次数。

很显然,这些问题主要都是底层支撑的 TCP 协议造成的。HTTP/2 都是使用 TCP 协议来传输的,而如果使用 HTTPS (HTTP over TLS) 的话,还需要使用 TLS 协议进行安全传输,而使用 TLS 也需要一个握手过程,这样就需要有两个握手延迟过程:

  • ①建立 TCP 连接的时候,需要和服务器进行三次握手来确认连接成功,也就是说需要在消耗完 1.5 个 RTT 周期之后才能进行数据传输。
  • ②建立 TLS 连接,TLS 有两个版本:TLSv1.2 和 TLSv1.3,不同版本建立连接所需 RTT 时间不同,大致需要 1~2 个 RTT 周期。

小贴士:RTT(Round-Trip Time,往返时延),是指数据从网络一端传到另一端所需的时间。

总之,在真正传输数据之前,就已经消耗了 3~4 个 RTT 周期,以在中国大陆访问美国的本土网站为例,中美直连的链路一般至少需要 100ms 时间(根据所处大陆地域不同存在些许差别,在北上广等国际出口城市)。因此在传输网络数据前,仅仅是建立 HTTPS 连接的 RTT 时间已经消耗了近 500ms 的时间。

上文在介绍 HTTP/2 时就提到了,HTTP/2 的一大改进就是多路复用,让多个请求存在于同一个 TCP “管道”中,如果网络连接差,比如存在大量丢包时,此时 HTTP/2 的性能还不如 HTTP/1 ,因为 TCP 协议的可靠特点,当出现丢包时,会触发重传机制,丢失的包会重新传输一次或者多次,直到接收方确认为止,当 HTTP/2 出现丢包时,整个 TCP 连接都要开始等待重传,就会阻塞此 TCP 管道中的所有请求。而对于 HTTP/1.1 来说,可以开启多个 TCP 连接,出现这种情况反到只会影响其中一个连接,剩余的 TCP 连接还可以正常传输数据。

实际上谷歌在开发 SPDY 协议时就意识到它存在的不足,因此同时开发了一个基于另一个传输层协议 UDP 的的 QUIC 协议,此协议就是 HTTP/3 的基础模型。在 2018 年 11 月互联网正式批准了 HTTP-over-QUIC 成为下一代 HTTP/3 协议,其在 HTTP/2 的基础上实现了很多飞跃,较完美的解决了队头阻塞问题。

由于 HTTP/3 基于用户数据报协议(UDP,User Datagram Protocol),此协议相比较于 TCP 可靠连接,最大的特点就是无状态、不可靠。因此可以实现 O 个 RTT 周期完成连接并开始传输数据,也就解决了队头阻塞问题。

基于对 NGINX 的补丁使其支持最新的 HTTP/3 协议

注意:截止本文发布时,此补丁仅仅支持 NGX 的稳定版本 1.16.1 。

下载源码

$ curl -O https://nginx.org/download/nginx-1.16.1.tar.gz
$ tar xvzf nginx-1.16.1.tar.gz

克隆补丁

$ git clone --recursive https://github.com/cloudflare/quiche

应用补丁

$ cd nginx-1.16.1
$ patch -p01 < ../quiche/extras/nginx/nginx-1.16.patch

编译

$ ./configure                               \
    --prefix=$PWD                           \
    --with-http_ssl_module                  \
    --with-http_v2_module                   \
    --with-http_v3_module                   \ # 启用 HTTP/3
    --with-openssl=../quiche/deps/boringssl \ # 使用谷歌的 BoringSSL 加密库
    --with-quiche=../quiche
$ make

小贴士:关于 BoringSSL 加密库的编译可以参考本站之前的文章,在相关文章中可以看到。

编译完成后,在运行程序时需要配置新的参数才能正常使用新协议。

http {
    server {
        # Enable QUIC and HTTP/3.
        listen 443 quic reuseport;

        # Enable HTTP/2 (optional).
        listen 443 ssl http2;

        ssl_certificate      cert.crt;
        ssl_certificate_key  cert.key;

        # Enable all TLS versions (TLSv1.3 is required for QUIC).
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

        # Add Alt-Svc header to negotiate HTTP/3.
        add_header alt-svc 'h3-23=":443"; ma=86400';
    }
}

这样同时启用了 HTTP/2 HTTP/3 并监听 TCP/443 与 UDP/443 端口

需要注意的是即便服务器端支持了 HTTP/3 协议,也需要客户端(浏览器等)支持新协议才能正常体验,当前仅有 Chrome CanaryFirefox Nightlycurl 支持新协议。

附录

相关链接

参考链接

如果遇到问题或者对文章内容存疑,请在下方留言,博主看到后将及时回复,谢谢!
回复
回答43+20=