因为这篇文章实在拖了太久,所以
Nginx
已经有官方实现了,详情请参见https://quic.nginx.org/
,但是这个实现是IETF QUIC,如果你想要兼容 gQUIC,请继续阅读
起因
什么是QUIC?
快速UDP网络连接
(英语:Quick UDP Internet Connections
,缩写:QUIC)是一种实验性的网络传输协议。由Google开发,在2013年实现。QUIC使用UDP协议。 2015年6月,QUIC的网络草案被正式提交至互联网工程任务组。2018 年 10 月,互联网工程任务组 HTTP 及 QUIC 工作小组正式将基于 QUIC 协议的 HTTP
(英语:HTTP over QUIC
)重命名为HTTP/3
以为确立下一代规范做准备。
我为什么应该使用QUIC?
理论上
QUIC旨在提供几乎等同于TCP连接的可靠性,但延迟大大减少。QUIC的另一个目标是提高网络切换期间的性能。
实际上
对于个人开发者而言,QUIC带来的提升其实并不明显 而且由于国内的网络环境,UDP包的QoS级别比TCP更低,很容易在网关处被
丢包,体验反而不如http/2
但是用上新技术本身就是目的)
操作
选择
个人用户的选择并不多,在不考虑自行开发的情况下,可供选择的只有cloudflare
开源的QUICHE
,或者使用caddy
作为反向代理单独监听UDP/443
,但是这些实现基本都是IETF QUIC
。
也就是说,市场主流的chrome及chromium浏览器
如果要使用QUIC连接的话,需要在启动项中单独添加参数,对用户并不友好。谷歌系目前默认启用的还是gQUIC
,即谷歌自己的实现。 我找来找去,找到一个由搜狐开源的patch。
准备源码
你需要一个可以运行的Linux实例
,保留50G以上的磁盘空间,推荐使用Ubuntu 18.04LTS
nginx-quic部分
git clone https://github.com/evansun922/nginx-quic.git
chromium部分
获取chromium源码
因为这个patch是基于chromium
的,需要获取chromium
的源码
警告
由于国内的特殊网络环境,这可能是最难的一步,请仔细阅读。
谷歌实在是太有钱了,所以几乎什么东西都自己做了一个,我们需要使用
depot_tools
来下载源码。
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=/path/to/depot_tools:$PATH
接下来,使用
fetch chromium
来获取源码,注意,fetch命令不支持断点续传,而且chromium
体积约为22G
,最好确认自己有一个稳定的科学环境再开始下载
当fetch
执行完成之后,你的工作目录里应当有
.gclient # A configuration file for you source checkout
src/ # Top-level Chromium source checkout.
执行
cd src && ./build/install-build-deps.sh
来安装必要的依赖,完成这几步后
gclient sync
来完成相应的hooks
检出对应版本源码
请检查nginx-quic
的最新commit,来确定自己应当使用的chromium版本。 比如,对于comiitd117af2
,我们可以得知对应的chromium
版本为86.0.4224.0
进入src
目录,运行
git checkout 86.0.4224.0
来检出对应版本,随后运行
gclient sync -D
来完成hooks。
nginx部分
从http://nginx.org/en/download.html
下载源码并解压即可
编译
进入nginx-quic
目录,运行
python3 mk2gn.py </path/to/nginx> </path/to/chromium/src> <args>
</path/to/nginx>: nginx源码根目录路径。
</path/to/chromium/src>: chromium源码src目录路径。
< args>: configure nginx时,所需的参数。
这里放上我的参数以作参考
python3 mk2gn.py "/home/zxilly/Downloads/nginx-1.19.2" \
"/home/zxilly/quic/quic/src" "--user=www --group=www \
--prefix=/www/server/nginx \
--add-module=/www/server/nginx/src/ngx_devel_kit \
--add-module=/www/server/nginx/src/lua_nginx_module \
--add-module=/www/server/nginx/src/ngx_cache_purge \
--add-module=/www/server/nginx/src/nginx-sticky-module \
--with-pcre=pcre-8.43 \
--with-http_v2_module \
--with-stream --with-stream_ssl_module --with-stream_ssl_preread_module \
--with-http_stub_status_module \
--with-http_ssl_module --with-http_image_filter_module \
--with-http_gzip_static_module \
--with-http_gunzip_module \
--with-http_sub_module \
--with-http_flv_module \
--with-http_addition_module \
--with-http_realip_module \
--with-http_mp4_module \
--with-ld-opt=-Wl,-E \
--with-cc-opt=-Wno-error \
--with-ld-opt=-ljemalloc \
--with-http_dav_module \
--add-module=/www/server/nginx/src/nginx-dav-ext-module \
--add-module=/root/ngx_brotli"
切换到chromium的src目录,执行
gn gen out/Release --args="is_component_build=false is_debug=false"
这时可以在net/BUILD.gn
文件中添加nginx编译需要的库文件和动态链接
如果直接添加库路径编译出错,可以把需要的头文件单独软链接到其他目录
executable("nginx") {
sources = [
# 所用到的.c或者.cc源码,一般不用修改
]
include_dirs = [
#头文件dir,类似与 "-I"
]
lib_dirs = [
# 库的搜索目录,类似与-L your libdir
]
libs = [
# dynamic library: pthread or static library: /path/xxx.a
]
cflags_c = [
# 编译选项
"-D_FORTIFY_SOURCE=2",
"-DTCP_FASTOPEN=23",
"-DNDK_SET_VAR",
]
}
执行ninja -C out/Release nginx
,编译好的nginx-quic就在out/Release
目录中。
执行./nginx -V
来检查编译是否成功
demo
如果你确定能够满足这些条件
那么你可能可以直接使用我编译好的nginx文件
配置文件
请参照 nginx-quic 文档
关于Alt-Svc
头部,提供一个参考
add_header alt-svc 'quic=":443";ma=500;v="50,48,47,46,44,43,39";h3-29=":443";ma=2592000;h3-28=":443";ma=2592000;h3-27=":443";ma=2592000;h3-25=":443";ma=2592000;h3-24=":443";ma=2592000;';
参考
[1] nginx-quic
[2] depot_tools_turtorial
发表回复