體驗 http3: 基於 nginx quic 分支

去年發過文章 HOL blocking 困擾兩個月的問題, http2 通過多路複用虛擬 stream 最大化的利用了 tcp 連接的性能,並且解決了七層的 HOL 問題,但是沒有解決四層 tcp 的 HOL, 如果有丟包,那麼同一 tcp 上的所有業務都會產生影響,QPS 高的時候非常明顯

而 QUIC[1] 解決了這個問題,底層基於 UDP. 本文提到的 http3 也是基於 google 的 quic, IETF 去年發佈了完整版的 RFC9000[2]

how-facebook-is-bringing-quic-to-billions[3] 提到了性能優化,整體來講弱網絡下,用戶體驗提升非常明顯,但是有一些基於 tcp 做的優化就不再適用了,需要重新審視一下。阿里也開源了自己的 XQUIC[4], 手淘大規模應用,網絡耗時降低超 20%

性能測試也可以參考 HTTP3/QUIC 性能測試與配套組件 [5] 和 measuring-quic-vs-tcp-mobile-desktop[6]

背景

微信羣有朋友將博客升級到了 http3, 諮詢一翻後我也升級了,基於 nginx 的 quic branch, 重新編譯即可,參數改動非常少,這裏得提一下芮神的 xiaorui.cc 到現在都沒有 tls... 感興趣的可以看看 https://mytechshares.com

編譯 H3

整體參考 nginx quic roadmap[7] 的 dockerfile

nginx quic 使用 boringssl, 無法科學上網的單獨下載吧

# apt-get install -y git gcc make g++ cmake perl libunwind-dev golang
# git clone https://boringssl.googlesource.com/boringssl
# mkdir boringssl/build
# cd boringssl/build
# cmake ..
# make

nginx 源碼並沒有用 github 管理,需要下載 hg

# apt-get install -y mercurial libperl-dev libpcre3-dev zlib1g-dev libxslt1-dev libgd-ocaml-dev libgeoip-dev
# hg clone https://hg.nginx.org/nginx-quic

編譯也比較簡單,沒啥特殊的

./auto/configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_realip_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt=-I../boringssl/include --with-ld-opt='-L../boringssl/build/ssl -L../boringssl/build/crypto' --with-http_v3_module  --with-stream_quic_module

重點是幾個 http3 相關的

--with-ld-opt='-L../boringssl/build/ssl -L../boringssl/build/crypto' --with-http_v3_module  --with-stream_quic_module

make 完成後將 nginx-quic/objs/nginx 命令複製到 /usr/sbin 即可

# nginx -V
nginx version: nginx/1.21.6
built by gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)
built with OpenSSL 1.1.1 (compatible; BoringSSL) (running with BoringSSL)
TLS SNI support enabled
......
ld-opt='-L../boringssl/build/ssl -L../boringssl/build/crypto' --with-http_v3_module --with-stream_quic_module

查看是編譯成功及參數

配置 H3

只需要在 nginx.conf 中添加下面四行即可,如果有多個 virtual server, 根據自己的情況調整

listen 443 http3 reuseport;
listen 443 ssl http2;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
add_header Alt-Svc 'h3=":443"; ma=86400, h3-29=":443"; ma=86400';

使用 nginx -T 檢測配置無後,重啓 nginx 即可

# ss -anlp | grep -i nginx
udp               UNCONN              0                    0                                                                                 0.0.0.0:443                                           0.0.0.0:*                                     users:(("nginx",pid=30595,fd=10),("nginx",pid=30594,fd=10),("nginx",pid=30593,fd=10))
udp               UNCONN              0                    0                                                                                 0.0.0.0:443                                           0.0.0.0:*                                     users:(("nginx",pid=30595,fd=6),("nginx",pid=30594,fd=6),("nginx",pid=30593,fd=6))
tcp               LISTEN              0                    128                                                                               0.0.0.0:443                                           0.0.0.0:*                                     users:(("nginx",pid=30595,fd=7),("nginx",pid=30594,fd=7),("nginx",pid=30593,fd=7))
tcp               LISTEN              0                    128                                                                               0.0.0.0:80                                            0.0.0.0:*                                     users:(("nginx",pid=30595,fd=8),("nginx",pid=30594,fd=8),("nginx",pid=30593,fd=8))
tcp               LISTEN              0                    128                                                                                  [::]:80                                               [::]:*                                     users:(("nginx",pid=30595,fd=9),("nginx",pid=30594,fd=9),("nginx",pid=30593,fd=9))

可以看到我們同時支持了 udp/tcp 的 443 和 80

開放防火牆

注意 iptables 是否開放了 udp 443, 以及雲廠商的安全組規則

我這裏需要開通阿里雲的

瀏覽器支持

對於 chrome 需要打開 chrome://flags/, 然後 enable QUIC

測試 H3

可以通過網站 https://http3check.net 來測試你的 blog 是否己支持 http3, 否則可能退化到 h2 或是 h1

最後打開 chrome 或是 firefox 測試完成 ^_^

小結

想了解 quic 協議的可以參考 a-quick-look-at-quic[8] 和 Everything You Need to Know About QUIC and HTTP3[9]

不是很清楚我司移動端是否使用 quic, 明天去問問,可能工具類的 APP 不如 facebook/youtube 對用戶體驗要求高。IDC 內網暫時沒升級 quic 的痛點,但也值得關注

寫文章不容易,如果對大家有所幫助和啓發,請大家幫忙點擊在看點贊分享 三連

關於 HTTP3 大家有什麼看法,歡迎留言一起討論,大牛多留言 ^_^

參考資料

[1]

chromium quic: https://www.chromium.org/quic/,

[2]

HTTP3 RFC9000: https://datatracker.ietf.org/doc/html/rfc9000,

[3]

how-facebook-is-bringing-quic-to-billions: https://engineering.fb.com/2020/10/21/networking-traffic/how-facebook-is-bringing-quic-to-billions/,

[4]

阿里正式開源自研 XQUIC: https://mp.weixin.qq.com/s/RdR-7hPfY3tckHt3c3bw7Q,

[5]

HTTP3/QUIC 性能測試與配套組件: https://segmentfault.com/a/1190000040394845,

[6]

measuring-quic-vs-tcp-mobile-desktop: https://blog.apnic.net/2018/01/29/measuring-quic-vs-tcp-mobile-desktop/,

[7]

nginx quic roadmap: https://www.nginx.com/blog/our-roadmap-quic-http-3-support-nginx/,

[8]

a-quick-look-at-quic: https://blog.apnic.net/2019/03/04/a-quick-look-at-quic/,

[9]

Everything You Need to Know About QUIC and HTTP3: _https://www.youtube.com/watch?v=QQX0Ezpq8U,

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/8CPWh_Ly61m8rkHvPT5n2g