相信大家已经或多或少的听说了HTTP/3或者QUIC,我就不在继续解释HTTP/3是什么了,反正是新一代的HTTP,并且基于UDP,不再受限于TCP三次握手四次挥手了;腾讯云的CDN也已经推出了收费的QUIC协议等等。
不过目前Nginx目前还没有正式启用HTTP/3及QUIC,倒是CloudFlare早已推出了Nginx的QUIC解决方案,LiteSpeed也已经在正式版中支持了HTTP/3。本文将带领大家在宝塔面板中在Nginx-quic[1]技术预览分支下编译Nginx。
本教程与Ubuntu 20.04版本完成,全程使用root用户,目录使用的是root的~目录,代码都保存在这里。操作前请先做好备份/快照,数据丢失及环境损坏与本教程无关
目前的Nginx QUIC解决方案
由官方推出的Nginx QUIC解决方案,目前还处于技术预览,与普通Nginx相同使用BSD协议,基于最新的1.21版本,并定时从主分支拉取代码。
本文以此方案来介绍。
最早的Nginx QUIC方案,基于Nginx 1.16.x
使用方法见:https://github.com/cloudflare/quiche/blob/master/nginx/README.md
国内用户不建议此方案,因为构建过程受国内网络愿意影响巨慢。
前置准备
首先你的宝塔Nginx需要是编译安装的1.21版本的Nginx,否则将缺少对应的依赖(/www/server/nginx/src
文件夹)。如果不是的话可以卸载后重新编译安装,注意备份nginx.conf
文件(/www/server/nginx/conf/nginx.conf)
然后是需要安装依赖,使用以下命令:
apt install build-essential ca-certificates zlib1g-dev libpcre3 libpcre3-dev tar unzip libssl-dev wget curl git cmake ninja-build golang hgsubversion
编译BoringSSL
Nginx的QUIC由谷歌的BoringSSL[2]提供支持,所以我们需要编译一下BoringSSL
git clone --depth=1 https://github.com/google/boringssl.git
cd boringssl
mkdir build
cd build
cmake -GNinja ..
ninja
cd ../..
如命令ninja
运行时出现网络错误,多半是go连接服务器出问题了,可以使用以下命令解决。
go env -w GOPROXY=https://goproxy.cn,direct
其他来自官方的编译方法见:https://github.com/google/boringssl/blob/master/BUILDING.md#building
获取Nginx-quic代码并编译
获取代码
nginx的代码使用的是hg
作为版本控制,和git
用法很像,刚刚我们也已经安装过了。使用以下命令获取源代码:
hg clone -b quic https://hg.nginx.org/nginx-quic
apt-get build-dep nginx # 安装nginx环境
获取宝塔Nginx的编译参数
运行以下命令:
/www/server/nginx/sbin/nginx -V
得到大概是以下结果:
root@VM-20-6-ubuntu:~$ nginx -V
nginx version: nginx/1.21.7
built by gcc 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
built with OpenSSL 1.1.1k 25 Mar 2021
TLS SNI support enabled
configure arguments: --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-openssl=/www/server/nginx/src/openssl --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-ipv6 --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
记住configure arguments
后面的参数,现在要对他进行修改。首先删除--with-openssl=...
参数(否则应该是编译不上),其次修改--with-pcre=pcre-8.43
为--with-pcre=/www/server/nginx/src/pcre-8.43
(就是补全了路径),最后就是添加HTTP/3模块参数--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的路径是否正确)
我的最终编译参数为:
--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=/www/server/nginx/src/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-ipv6 --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 --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'
编译Nginx-quic
使用以下命令来生成配置:
cd nginx-quic
./auto/configure --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=/www/server/nginx/src/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-ipv6 --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 --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'
后面那一大串就是刚刚拼接的字符串。
接下来删除objs/Makefile
文件第三行的-Werror
参数(编译中会有警告,有这个参数就会变成错误构建失败)
然后再nginx-quic
目录下运行make就可以开始编译了
make
没有出错就说明编译成功了。如果编译成功的话,在~/nginx-quic/objs/
目录下面应该会出现一个名为nginx的文件。
替换原本的Nginx
使用以下命令替换原本的Nginx
mv /www/server/nginx/sbin/nginx{,.bak} # 备份原本的Nginx文件
cp objs/nginx /www/server/nginx/sbin
make upgrade
没有出错的话就是升级成功了。
配置网站的HTTP/3
修改网站配置文件
网站首先要配置了HTTPS,点开他的”配置文件“,加入以下内容:
listen 443 http3 reuseport; # 代表开启HTTP/3
add_header Alt-Svc 'h3=":443"; ma=86400'; # 通知浏览器可以使用HTTP/3
开放服务器防火墙443端口的UDP协议
这一步是烦我最长时间的一步,宝塔的安全组默认显示443端口UDP开放,实际上并没有,需要手动修改以下。可以使用宝塔应用”系统防火墙“便捷操作。
点击上图中443端口的修改然后直接保存或删除重新添加443端口即可(协议一定要选TCP/UDP)
开放服务器安全组的443端口UDP协议
一般服务器提供商会有一个安全组来控制服务器的访问,在提供商那里把443端口的UDP加上就行了
检验HTTP/3是否生效
如果你是Firefox用户,可以直接在开发者工具的网络栏看到HTTP版本:
如果没有Firefox,可以使用https://http3check.net/来检测自己的网站是否支持HTTP/3及QUIC:
完成我自己的服务器的升级后,我自己也做了一个测试你的浏览器是否正在使用HTTP/3的小网页,欢迎大家也来参观~ https://h3.orangii.cn/
本文参考:节点边缘博客文章[3]
这种协议在nginx运行还不稳定,所以说我现在目前只能退回HTTP 2.0了,应该不是网络问题,因为用另外一个就不会这样专门为HTTP3衍生的openlitespeed,但是那样并发量一大照样会把机器给整宕机了 所以现在的配置是重新优化过后的,速度应该更快
我发现你的quic加载起来丝滑流畅,不知道为啥我配置的一卡一卡的跟鬼畜一样。
感觉你的也不慢,优化做的也可以,猜一下你可能是说图片一卡一卡吗?可以试试用一些CDN或者对象存储的图片优化来预先处理一下,我在图片的地方用了这个
我想说的是到目前为止使用nginx去做HTTP3quic协议的访问,总是会一卡一顿的和宝塔的默认编译环境目前不是高度兼容,我的页面用的前后端在我已知的知识范畴不论是压缩还是静态化缓存还是redis查询缓存自然不会太慢,更何况连个内容都没有。 如果没在你博客上评论,留下自己的域名,说直白点,也没其他什么人去访问不存在带宽的拥塞 cdn的作用意义不大,取源反倒没有直接访问的快。因为本来就是国内主机加上贷款并不小,包括https访问加密我也特意为改为128位,减少服务器和访客解密消耗
那就只能说是见仁见智了,有些时候不同人访问不同环境表现也不一样了。反正咱也是做的个人站长,肯定是自己喜欢怎么样就怎么搞是最好了。QUIC这个最后谁知道到底被谁影响了导致一卡一卡呢,没准还跟HTML结构有关系,但是那就很深入了
我重新配置了一下环境,现在应该更快了。最少的占用去访问😏
现在 QUIC 分支合了 1.23 的主线,部分依赖在 1.23 这个版本都得重新拉取源码了
比如
lua_nginx_module
和nginx-sticky-module
,不然编译疯狂报错另外由于
nginx-sticky-module
年久失修,在 BitBucket 上翻到了个针对 1.23 版本修复的 PR,按照提供的办法修改文件,亲测有效感谢提出~![](data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iZW1vdGlvbi1sb2FkaW5nIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9Ii04IC04IDQwIDQwIiBzdHJva2U9IiM4ODgiIG9wYWNpdHk9Ii41IiB3aWR0aD0iNjAiIGhlaWdodD0iNjAiPgogIDxwYXRoIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGQ9Ik0xNC44MjggMTQuODI4YTQgNCAwIDAxLTUuNjU2IDBNOSAxMGguMDFNMTUgMTBoLjAxTTIxIDEyYTkgOSAwIDExLTE4IDAgOSA5IDAgMDExOCAweiIvPgo8L3N2Zz4=)
另外最近没时间管博客也有点年久失修了
虽然但是,我自己重新编译的时候被 ngx-lua 这个模块卡住了,好不容易编译好了平滑升级(
make upgrade
)失败就很难受(所以大佬哪天有空重置下教程呗|´・ω・)ノ
回头我也得先试试,不然从技术就要变成寄术了
逛了一下宝塔论坛,里面一堆人反馈说 Nginx 1.23 没法用,要不就是编译失败(原因还就是上面提到的模块年久失修),要不就是无法兼容宝塔的插件。官方已经开摆叫润回 1.22 了。
隔壁 ngx_lua 的 issues 也有人反馈说模块不支持 QUIC 分支的编译。
我还是暂时用 quiche 打补丁的吧(
乐,不知道宝塔那边怎么考虑的了,一直是开心版的宝塔也一直没有更新过。之前说的更新教程也因为考研和各种其他事情摆烂很久没有更新,还有设置默认头像的那片文章![](data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iZW1vdGlvbi1sb2FkaW5nIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9Ii04IC04IDQwIDQwIiBzdHJva2U9IiM4ODgiIG9wYWNpdHk9Ii41IiB3aWR0aD0iNjAiIGhlaWdodD0iNjAiPgogIDxwYXRoIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGQ9Ik0xNC44MjggMTQuODI4YTQgNCAwIDAxLTUuNjU2IDBNOSAxMGguMDFNMTUgMTBoLjAxTTIxIDEyYTkgOSAwIDExLTE4IDAgOSA5IDAgMDExOCAweiIvPgo8L3N2Zz4=)
我这个教程编译完是 Nginx 1.21.7,用的 QUIC 分支的
changeset: 7870:55b38514729b
只能说估计宝塔那边可能还不一定找到我发的这个 PR(
没那个能力你知道么而且考虑到隔壁(ngx_lua)都还没确定说完全适配 QUIC 分支,所以在宝塔下目前还是折腾 Quiche 打补丁吧(反正我是国外服务器不用担心连接问题
唉突然想起来那个补丁的速度…
要不是已经忘了,应该可以把编译好的NGINX二进制文件发出来
确实(
宝塔下参数相同系统相同应该编译出的二进制文件都能跨服务器用吧?
好了,跟宝塔那边反馈那个 nginx-sticky-module 的那个 PR 了,并且官方那边测试没问题。链接
现在等官方看怎么用这个PR了(
φ( ̄∇ ̄o)
看着真不错,但想想还是懒得编译了,等以后各大厂商适配了再上
各大厂商指的是什么,Nginx不就一个组织吗![](data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iZW1vdGlvbi1sb2FkaW5nIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9Ii04IC04IDQwIDQwIiBzdHJva2U9IiM4ODgiIG9wYWNpdHk9Ii41IiB3aWR0aD0iNjAiIGhlaWdodD0iNjAiPgogIDxwYXRoIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxLjUiIGQ9Ik0xNC44MjggMTQuODI4YTQgNCAwIDAxLTUuNjU2IDBNOSAxMGguMDFNMTUgMTBoLjAxTTIxIDEyYTkgOSAwIDExLTE4IDAgOSA5IDAgMDExOCAweiIvPgo8L3N2Zz4=)
是不是,各个浏览器或者类似宝塔这样的管理平台吧。估计宝塔会在QUIC合并到主分支,更新最新版本号的时候支持吧
各个浏览器和宝塔,等社会面都支持了我再选择升级,不想折腾
当时HTTP/2是RFC 7540提出的,在2015年五月,百度搜的相关文章大都在2017年;所以作为对比,QUIC (RFC 9000)这个基于UDP的传输协议及HTTP/3 草案,估计要想基本全面实现估计还有个几年的时间
学到了,感谢大佬分享!
学习啦,谢谢分享。。。
现在应该还有很多浏览器不支持http3吧,这样整会不会影响兼容性导致一些用户无法打开网站
最新版的Firefox及Chrome都已经默认QUIC的开启了,事实上浏览器都是先向TCP 443端口发起请求,当看到
h3=":443"; ma=86400
header 的时候才会去尝试HTTP/3,也就是说是兼容HTTP/2及1.1的