Nginx 中启用 HTTP/3
上一篇文章中,介绍了 Http/3 的基本原理和优化,本节介绍下如何在 CentOS 7 环境上通过 Nginx 启用 Quic 协议
环境准备
如果不愿意折腾,可以在文末下载博主编译好的 nginx-quic 可执行文件,跳过坎坷的编译安装步骤(),快速体验
准备编译环境
yum install -y build-essential ca-certificates zlib1g-dev libpcre3 libpcre3-dev tar unzip libssl-dev wget curl git cmake3 ninja-build golang
# 然后执行
yum install -y hgsubversion
升级 GCC
注意,CentOS 通过 yum 直接安装、升级的 GCC 版本过老,并不能直接使用,需要进行升级。升级时推荐采用下列的办法进行升级。当然也可以手动编译 GCC 的源码来级,但是会更加……坎坷。
# 安装 devtoolset-9
yum install devtoolset-9
安装好后,替换掉系统的 gcc, g++, c++
# 备份原gcc, g++, c++
cp /usr/bin/gcc /usr/bin/gcc4.8.5
cp /usr/bin/g++ /usr/bin/g++4.8.5
cp /usr/bin/c++ /usr/bin/c++4.8.5
# 设置软连接
ln -s /opt/rh/devtoolset-9/root/bin/gcc /usr/bin/gcc
ln -s /opt/rh/devtoolset-9/root/bin/g++ /usr/bin/g++
ln -s /opt/rh/devtoolset-9/root/bin/c++ /usr/bin/c++
准备好后,执行 c++ --version
,即可查看当前使用的 C++ 版本
需要注意,需要 9 以上版本,否则无法编译
安装
编译安装 BoringSSL
编译安装谷歌的 boringSSL,以获得 QUIC 支持,后面编译 nginx-quic 需要使用
# 克隆 Boringssl 代码
git clone --depth=1 https://github.com/google/boringssl.git
# 修改 CMakeList.txt 文件,添加如下内容(用于解决某些情况下的报错,可以先跳过,如遇报错再来添加)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-implicit-fallthrough -Wno-format-signedness")
# 编译安装
cd boringssl
mkdir build
cd build
cmake -GNinja ..
ninja
编译安装 Nginx-quic
首先获取 Nginx 的编译参数,即 nginx -V
指令回显中的 configure arguments 项
将该项的 --with-openssl
删除后,在末尾添加 --with-http_v3_module --with-stream_quic_module --with-cc-opt=-I../boringssl/include --with-ld-opt='-L../boringssl/build/ssl -L../boringssl/build/crypto
后,记下来,后续编译时需要使用
需要注意 BoringSSL 的路径,要指向上一步的使用的 boringSSL 路径
# 获取 Nginx-quic 代码,或者去网站下载自己需要的版本:https://hg.nginx.org/nginx-quic/tags
hg clone -b quic https://hg.nginx.org/nginx-quic
# 编译安装
cd nginx-quic
./auto/configure 上面记下来的选项,拷到这里
# 一核就 -j2,四核就 -j8
make -j2
结束后,Nginx 二进制文件会生成在 objs 路径下
启用
替换 Nginx
# 查看当前用的 Nginx 在哪
which nginx
# 备份
cp /Nginx路径/nginx /Nginx路径/nginx_bak
# 替换为 Nginx-quic
cp ./objs/nginx /Nginx路径/
make upgrade
修改 Nginx 配置文件
Nginx 配置文件通常会在 /etc/nginx/nginx.conf
,修改其中的内容如下
server {
# 注意是 Http2
listen 443 ssl http2;
# 加上这行,注意是 QUIC,http3 已弃用
listen 443 quic reuseport;
server_name 域名;
ssl_certificate /证书路径.crt;
ssl_certificate_key /证书路径.key;
ssl_session_cache shared:SSL:1m;
location /home/ {
# 加上这行
add_header Alt-Svc 'h3=":443"; ma=86400';
root /home/www;
index index.html index.htm;
}
}
修改完成后,执行 nginx -s reload
以更新配置
此时如果 Nginx 会监听 443 的 UDP 端口,说明配置成功,可以执行 lsof -i:443
进行查看,可以得到如下显示
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 3267 www 7u IPv4 33064242 0t0 TCP *:https (LISTEN)
nginx 3267 www 11u IPv4 33591364 0t0 UDP *:https
nginx 12777 root 7u IPv4 33064242 0t0 TCP *:https (LISTEN)
nginx 12777 root 11u IPv4 33591364 0t0 UDP *:https
端口放行
需要为 443 端口的 UDP、TCP 协议开启放行
客户端设置
Chrome 浏览器可以访问 chrome://flags,搜索 quic 开启 QUIC 支持
浏览器启用后,可以通过这个 URL 进行测试,页面上会提示你的浏览器是否可以使用 QUIC
需要注意,如果开启了代理服务,可能导致 QUIC 不生效,需要关掉后进行测试
参考
Http/3.0 测评
多资源
在一个页面中加载大量资源,下列各图为单个页面加载 200 个单像素图片,在 Http 各协议环境下的效果
浏览器为 Http/1.1 开启了 6 个连接来处理这些图片的请求
结论:在 Http/2 和 Http/3 中,浏览器都复用单个连接来加载资源,比 6 个连接的 Http/1.1 速度还快很多,可见 Http/2 的优化不是盖的,而且 Http/3 完全保留了这些特征。但是 Http/2 和 Http/3 相比差距不大。
大文件
Http/3.0 加载大文件时表现怎样,直接上图,作为对照,先看 Http/2 的表现:
Http/2 协议下,2M 带宽加载 5M 的文件,耗时 16.23s,算是跑满了带宽,估计 Http/3 也出色不了更多
不是放错图了,它确实报错了。测试期间切换了各种时间、空间,更换了各种网络环境,开关了系统的各种代理、VPN 设置,都是这个结果:加载途中中断。
进行一番搜索,发现也有不少人遇到这个问题的样子,解决办法似乎只有关掉 QUIC 支持这一个办法能彻底奏效~~(那还测个寂寞呀)~~。
结论:貌似 QUIC 的应用现阶段似乎还是不太成熟的(本打算跳过这个测试的,但测试的目的并不是为了给 QUIC 打广告)
网络延迟环境
500ms 延迟
在具有一定延迟的环境下,Http/2 和 Http/3 的差距已经很明显,或者说基本没差别
5s 延迟
在高延迟的网络环境下,Http/3 的表现仍然很出色
结论:QUIC 在高延迟的网络环境下表现很优秀
丢包网络环境
20% 丢包
在具有一定丢包的网络环境下,http/3 的表现比 Http/2 优秀不少
50% 丢包
在高丢包的网络环境下,Http/2 的表现十分尴尬,但 Http/3 受到的影响却很小
结论:QUIC 在高丢包的网络环境下表现极佳
后记
Http/3.0 在弱网环境(丢包、延迟)下,表现比较优秀。但是与过去不同,现在通常使用的网络状况都比较良好,HTTP/3 的优势似乎并没办法发挥出来。
- clumsy-弱网络模拟
- 编译后好的 Nginx-Quic 二进制文件,即上文提到的
objs/nginx
文件:分享地址