一.HTTP/3和QUIC的基本原理
1.什么是http3?
HTTP/3 是即将到来的第三个主要版本的HTTP协议,使用于万维网。与其前任HTTP/1.1和HTTP/2不同,在HTTP/3中,将弃用TCP协议,改为使用基于UDP协议的QUIC协议实现。
2.解决什么问题?
此变化主要为了解决HTTP/2中存在的队头阻塞问题。由于HTTP/2在单个TCP连接上使用了多路复用,受到TCP拥塞控制的影响,少量的丢包就可能导致整个TCP连接上的所有流被阻塞。
3.发展历史:
QUIC(快速UDP网络连接,即Quick UDP Internet Connections)是一种实验性的网络传输协议,由Google开发,该协议旨在使网页传输更快。在2018年10月28日的邮件列表讨论中,互联网工程任务组(IETF) HTTP和QUIC工作组主席Mark Nottingham提出了将HTTP-over-QUIC更名为HTTP/3的正式请求,以“明确地将其标识为HTTP语义的另一个绑定……使人们理解它与QUIC的不同”,并在最终确定并发布草案后,将QUIC工作组继承到HTTP工作组。在随后的几天讨论中,Mark Nottingham的提议得到了IETF成员的接受,他们在2018年11月给出了官方批准,认可HTTP-over-QUIC成为HTTP/3。
关于quic的详细介绍,可以参考:https://blog.cloudflare.com/the-road-to-quic/
2019年9月,HTTP/3支持已添加到Cloudflare和Google Chrome(Canary build)。Firefox Nightly将在2019年秋季之后添加支持。
截至2021年1月,HTTP/3仍然是草案状态
参考:from:https://zh.wikipedia.org/wiki/HTTP/3
4.优势有哪些?
- 基于UDP减少了TCP三次握手及TLS握手时间
- 解决多路复用丢包时的线头阻塞问题
- 优化重传策略
- 流量控制
- 连接迁移
二.HTTP/3和QUIC的实现方式
1.方案选择
对于HTTP3.0,由于整个协议还是处于草案阶段,目前来说没有一个完整的标准,对于Nginx来说,支持HTTP3.0目前有两种方案可以选择:
- 基于Cloudflare的分支版本Nginx:对于HTTP3.0/QUIC,Cloudflare始终走在了前列,借助于自家维护的开源项目quic,从Nginx中拉出了一个分支来开发,并编译出了对HTTP3.0支持的Nginx服务器。
- Nginx官方Nginx-quic项目:去年6月10日,Nginx官博发布公告称已经在研发支持HTTP3.0/QUIC协议的工作,目前项目维护在nginx-quic,该项目和基于Cloudflare基于Nginx的分支并无关系,算是相对于正统的方案。
2.下面采用基于Cloudflare的分支版本Nginx的方式实现http/3
a.系统环境及相关依赖的软件安装和升级
[root@li1548-187 ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
[root@li1548-187 ~]# uname -a
Linux li1548-187 3.10.0-957.12.2.el7.x86_64 #1 SMP Tue May 14 21:24:32 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
#TLS1.3 需要 OpenSSL 1.1.1 以上版本,系统自带版本一般较旧,我们需要重新安装(但是下文中的 quiche patch 中已经内置了 Boringssl,不需要再重新安装,我这里就不用系统的OpenSSL,而使用boringssl)
#安装openssl1.1.1
yum install -y openssl-devel openssl11 openssl11-devel
编译主要需要注意的问题是设置编译FLAG,以便使用最新的openssl库
export CFLAGS=$(pkg-config --cflags openssl11)
export LDFLAGS=$(pkg-config --libs openssl11)
PS:关于什么是boringssl,请参考下面的链接:
1)https://boringssl.googlesource.com/boringssl/
2)https://imququ.com/post/optimize-ssl-ciphers-with-boringssl.html
3)系统的gcc的版本一定要至少大于4.9,否则在编译Nginx的时候会出错,升级gcc请参考:https://teddylu.xyz/blog/4149.html
#安装rust,为了支持 quiche,Rust 需要至少 1.39 版本
yum install clang go rust cargo -y
#下载 Brotli:
Brotli is a generic-purpose lossless compression algorithm (Brotli是一种通用无损压缩算法)that compresses data using a combination of a modern variant of the LZ77 algorithm, Huffman coding and 2nd order context modeling, with a compression ratio comparable to the best currently available general-purpose compression methods. It is similar in speed with deflate but offers more dense compression.
git clone https://github.com/google/ngx_brotli
cd ngx_brotli
git submodule update --init
#升级cmake的版本,否则编译的时候会出现错误:CMake 3.0 or higher is required. You are running version 2.8.12.2
wget https://cmake.org/files/v3.20/cmake-3.20.0-rc5.tar.gz
cd cmake-3.20.0-rc5/
./bootstrap
gmake
gmake install
如果本地使用了yum进行安装过,则需要卸载
[root@li1548-187 cmake-3.20.0-rc5]#yum remove cmake -y
[root@li1548-187 cmake-3.20.0-rc5]# ln -s /usr/local/bin/cmake /usr/bin/cmake
[root@li1548-187 cmake-3.20.0-rc5]# cmake --version
cmake version 3.20.0-rc5
CMake suite maintained and supported by Kitware (kitware.com/cmake).
#安装新版本的perl
wget https://www.cpan.org/src/5.0/perl-5.30.3.tar.gz tar xf perl-5.30.3.tar.gz cd perl-5.30.3 ./Configure -des -Dprefix=/usr/mysf make make test make install
# 建立新的软链接
mv /usr/bin/perl /usr/bin/perl.bak
ln -s /usr/mysf/bin/perl /usr/bin/perl
# 检查是否安装成功
perl -v
[root@li1548-187 teddylu]# perl -v
This is perl 5, version 30, subversion 3 (v5.30.3) built for x86_64-linux
b.目前,最新版本的 nginx (nginx-1.19.0) 仍然不能原生支持 HTTP3,好在 CloudFlare 提供了基于 Quiche 和 Boringssl 实现的一个 patch,使得我们可以在 nginx 上尝鲜一下。下载最新版本 nginx 并打上 quiche 的 patch
wget http://nginx.org/download/nginx-1.19.0.tar.gz
tar xf nginx-1.19.0.tar.gz
[root@li1548-187 ~]# git clone --recursive https://github.com/cloudflare/quiche
Cloning into 'quiche'...
remote: Enumerating objects: 252, done.
remote: Counting objects: 100% (252/252), done.
remote: Compressing objects: 100% (139/139), done.
remote: Total 13454 (delta 128), reused 184 (delta 98), pack-reused 13202
Receiving objects: 100% (13454/13454), 15.60 MiB | 13.11 MiB/s, done.
Resolving deltas: 100% (7253/7253), done.
Submodule 'boringssl' (https://github.com/google/boringssl.git) registered for path 'deps/boringssl'
Cloning into 'deps/boringssl'...
remote: Enumerating objects: 477, done.
remote: Counting objects: 100% (477/477), done.
remote: Compressing objects: 100% (304/304), done.
remote: Total 80174 (delta 279), reused 295 (delta 161), pack-reused 79697
Receiving objects: 100% (80174/80174), 165.46 MiB | 27.14 MiB/s, done.
Resolving deltas: 100% (56884/56884), done.
Submodule path 'deps/boringssl': checked out '067cfd92f4d7da0edfa073b096d090b98a83b860'
#打入quiche的path,官方说是支持nginx-1.16.1版,其实nginx-1.19.0版也是支持的
[root@li1548-187 ~]# tar xf nginx-1.19.0.tar.gz
[root@li1548-187 ~]# cd nginx-1.19.0
[root@li1548-187 nginx-1.18.0]# patch -p01 < ../quiche/extras/nginx/nginx-1.16.patch
c.安装 nginx(编译的时候一定要升级gcc,否则会报错,参考:https://teddylu.xyz/blog/4149.html)
./configure \ --prefix=/application/nginx-1.19.0 \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_v3_module \ --with-http_gzip_static_module \ --with-http_realip_module \ --with-http_geoip_module \ --with-threads \ --with-stream \ --with-quiche=/root/quiche \ --with-openssl=/root/quiche/deps/boringssl \ --with-http_stub_status_module
make && make install
d.配置nginx
listen 443 quic reuseport;
listen 443 ssl http2 fastopen=3 reuseport;
listen [2400:8002::f03c:91ff:fpe0:7653]:443 ssl http2;
listen [2400:8002::f03c:91ff:fpe0:7653]:443 quic;
PS:为啥要同时启用http2和http3的ipv4和ipv6呢?
a.一个是因为我机器上有2种类型的ip
b.如果只启用http/3的而不启用http2,那么所有使用不支持http/3的浏览器的用户将无法访问网站,所以这样做的目的是同时兼顾只能使用支持http/2的浏览器的用户!!!
#要支持quic必须要开启TLSv1.3
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
#Alt-Svc响应头
add_header alt-svc ‘h3-27=”:443″; ma=86400,h3-29=”:443″; ma=86400’;
3.测试HTTP/3支持
UDP端口测试
QUIC-HTTP/3是基于UDP协议的,因此需要开放服务器的UDP 443端口
#ipv4
-A INPUT -p udp -m udp –dport 443 -j ACCEPT
#ipv6
-A INPUT -p udp -m state –state NEW -m udp –dport 443 -j ACCEPT
以上是针对既有ipv4也有ipv6的机器上,分别在其对应的防火墙上开启udp的443端口
在本地电脑上,执行下面的命令:
nc -v -u 1.2.3.4 443
其中,1.2.3.4为您的服务器IP地址,若收到类似下面的回显,则说明进入服务器的UDP 443端口开放了。
[root@docker02 ~]# nc -v -u 1.2.3.4 443
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 1.2.3.4:443.
[root@docker02 ~]# nc -v -u google.com 443
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 93.46.8.90:443.
网站测试
目前,有两个网站可以用来测试我们的网站是否支持QUIC-HTTP/3。
这两个网站分别是:
输入自己的域名即可测试网站是不是支持http/3
浏览器开启http3
Firefox开启http3
首先在火狐地址栏输入:about:config
然后搜索http3,找到network.http.http3.enabled
把 false
改成 true
,重启、就可以了。
Chrome canary开启http3
注意,只有金丝雀版chrome才支持http3,在地址栏输入 chrome://flags/
搜索quic,找到Experimental QUIC protocol
把Default
改成Enabled
,重启浏览器。
然后,在Chrome canary的快捷方式,右键、属性,在目标栏尾处添加--enable-quic --quic-version=h3-29
即可。
最后,在浏览支持http3的网站时,按f12键可以查看网络、协议显示为HTTP/3或者h3-29.
(ps.使用Google Chrome Canary没有看到页面显示为http/3,原因待查!!!)
修正:
下面是firefox浏览器的对源站和cloudflare站点的http/3的支持的具体的信息:


参考:
https://starts.sh/posts/nginx_http3.html