实践HTTP3/QUIC

为优化全链路耗时,尽可能缩短建连时间,实践下H3.

H3是否能打通,可以拆分为3块

  1. 服务端支持H3协议
  2. H3链路是否畅通
  3. 客户端/Chrome需要支持H3协议

服务端支持H3协议

以 Nginx 为例,其他同理。默认站点已支持H2,且TLS版本支持1.3。

必要配置

  1. 开启监控
    1
    listen 443 quic reuseport;
  2. add_header
    1
    add_header alt-svc 'h3=":443"; ma=2592000, h3-29=":443"; ma=2592000, h3-Q050=":443"; ma=2592000, h3-Q046=":443"; ma=2592000, h3-Q043=":443"; ma=2592000, quic=":443"; ma=2592000; v="43,46"';

nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
server
{
listen 80;
listen 443 ssl ;
#listen [::]:443 ssl;
listen 443 quic reuseport;
#listen [::]:443 quic reuseport;
http2 on;
server_name rencheng.cc www.rencheng.cc;
index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/rencheng.cc;

#SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则
#error_page 404/404.html;
#HTTP_TO_HTTPS_START
if ($server_port !~ 443){
rewrite ^(/.*)$ https://$host$1 permanent;
}
#HTTP_TO_HTTPS_END
ssl_certificate /www/server/panel/vhost/cert/rencheng.cc/fullchain.pem;
ssl_certificate_key /www/server/panel/vhost/cert/rencheng.cc/privkey.pem;
ssl_protocols TLSv1.3;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
#ssl_early_data on;
add_header Strict-Transport-Security "max-age=31536000";
add_header alt-svc 'h3=":443"; ma=2592000, h3-29=":443"; ma=2592000, h3-Q050=":443"; ma=2592000, h3-Q046=":443"; ma=2592000, h3-Q043=":443"; ma=2592000, quic=":443"; ma=2592000; v="43,46"';
error_page 497 https://$host$request_uri;
#SSL-END

#ERROR-PAGE-START 错误页配置,可以注释、删除或修改
error_page 404 /404.html;
error_page 502 /502.html;
#ERROR-PAGE-END

#PHP-INFO-START PHP引用配置,可以注释或修改
include enable-php-00.conf;
#PHP-INFO-END

#REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
include /www/server/panel/vhost/rewrite/rencheng.cc.conf;
#REWRITE-END

#禁止访问的文件或目录
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
{
return 404;
}

#一键申请SSL证书验证目录相关设置
location ~ \.well-known{
allow all;
}

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
error_log /dev/null;
access_log /dev/null;
}

location ~ .*\.(js|css)?$
{
expires 12h;
error_log /dev/null;
access_log /dev/null;
}
access_log /www/wwwlogs/rencheng.cc.log;
error_log /www/wwwlogs/rencheng.cc.error.log;
}

确保H3链路畅通

服务侧各节点防火墙开启udp流量

  1. 云实例的安全防火墙
  2. 服务器内防火墙打开,以宝塔为例

确保网络中间链路畅通

  1. 路由器支持udp流量
  2. 代理服务器支持udp流量
  3. 本地是否开启了代理(如果开启,需要关闭,目前为止大部分代理工具不支持udp流量转发)
  4. 首次使用流量测试,避免因为不确定WIFI连接的链路是否支持

测试H3是否连通

  1. 使用外部测试站点http3check.net

  2. 测试通过后,Chrome 需要设置开启 HTTP3,在chrome地址栏输入chrome://flags,搜索Experimental QUIC protocol,将default改为enable后重启即可。

  3. 多次清除缓存确认是否支持H3
    Xnip2024-09-12_17-48-46

iOS客户端支持H3

技术选型

  1. 方案一:由于iOS系统URLSession是在iOS 14.5开始支持的,如果仍然想使用URLSession的方式请求,并不能覆盖老系统。推荐等级⭐️⭐️。
  2. 方案二:使用Cronet,该方案的思路是通过URLProtocol的方式拦截到所有请求后,重定向到其内部发送H3请求,但需要研发对源码熟悉后精简功能,以减少对包体积的影响。。推荐等级⭐️⭐️⭐️。
    1. 无用的内部逻辑,例如 HTTP 模块里包含了很多浏览器才会用到的代码和功能;无
    2. 需用到的的协议,例如 FTP、Websocket 等;
    3. 与 quic 无关的功能模块,例如 tcp 连接池等。
  3. 方案三:使用大厂对Cronet精简过的库,优势是可以轻松迁移新版本,且大厂对其增加了很多功能,但是其对客户端支持还不完善,需要后续支撑好再进行接入是最好的。推荐等级⭐️⭐️⭐️⭐️。

架构低成本实践路线

  1. 先使用Apple的API让高版本系统客户端使用
  2. Cronet接入(缺点:包体积会增大)
  3. 接入成熟的大厂框架(减少包体积,体验一些实用功能)

在iOS上的实践

详见DEMO