🤪亲 http/2和3 真会用吗?

发布于:2024-05-06 ⋅ 阅读:(16) ⋅ 点赞:(0)

背景

记录一下nginx配置

http/2

nginx 版本: > 1.9.5

 server {
        #  开启http2
        listen 3839 ssl http2;
        # http2 单连接处理请求数量,默认1k,达到上限会要求建立新的连接,http2_max_requests已废弃
        keepalive_requests 10000;
        # 并发HTTP / 2流的最大数量。
        http2_max_concurrent_streams 128;
        # 空闲断开时间,默认30s, http2_recv_timeout已废弃
        client_header_timeout 10s;

        # SSL证书
        ssl_certificate      /ssl/selfsigned.pem;
        ssl_certificate_key   /ssl/selfsigned.key;
  }

注意:
浏览器中的 http2 必须的加 SSL,如果是服务之间调用则不需要,http2 与 SSL 是独立的两个东西不相关,但浏览器中 http2 强制必须加 SSL,非浏览器中使用可以不加 SSL

http1 效果图

2024-05-03-13-17-15.png

htttp2 效果图

2024-05-03-14-08-22.png

完美了

http/3

nginx 版本: >= 1.25.0 ( HTTP/3 仍处于实验阶段)

http3 比较特殊 走 UDP 协议并且强制使用 SSL
浏览器默认是 TCP 所以有个升级的过程,可以使用两个端口 A 升级到 B ,也可以使用 reuseport 参数端口复用

方式一,复用端口


 server {
        # 开启http3, reuseport 为共用端口,这样可以http2和http3共用一个端口了
        listen 8080  quic  reuseport;
        # 兜底降级处理,如果没有此配置则只支持http3,浏览器默认还是走TCP所以,只能用其他端口的Alt-Svc字段指定升级到此端口或用支持http3的工具请求
        listen 8080  ssl ;
        # 启用http2
        http2 on;
        # 根据需要启用 QUIC 重试
        quic_retry on;
        # SSL证书
        ssl_certificate      /ssl/selfsigned.pem;
        ssl_certificate_key   /ssl/selfsigned.key;

        # 告诉客户端支持http3 并且在3839端口,ma为有效期(单位s, 不写默认1天,别设置太长不然降级后必须失效才会升级)
        add_header Alt-Svc 'h3=":8080"; ma=10'; # 不可设置多个版本,Chrome 124 测试设置设置 h3-27=:8080"; ma=10,h3-29=":8080"; ma=10 会导致不升级到h3
  }

方式二,两个端口分开

例: 从 8081 升级到 8080

     server {
        #  开启http2
        listen 8081 ssl;
        # 开启http2,新版不写在listen中了
        http2 on;

        # http2 单连接处理请求数量,默认1k,达到上限会要求建立新的连接,http2_max_requests已废弃
        keepalive_requests 10000;
        # 并发HTTP / 2流的最大数量。
        http2_max_concurrent_streams 1280;
        # 空闲断开时间,默认30s, http2_recv_timeout已废弃
        client_header_timeout 10s;


        # SSL证书
        ssl_certificate      /ssl/selfsigned.pem;
        ssl_certificate_key   /ssl/selfsigned.key;

        # 告诉客户端支持http3 并且在8080端口,ma为有效期单位秒
        add_header Alt-Svc 'h3=":8080";ma=10';
     }

      server {
        # 开启http3
        listen 8080  quic;
        # 根据需要启用 QUIC 重试
        quic_retry on;


        # SSL证书
        ssl_certificate      /ssl/selfsigned.pem;
        ssl_certificate_key   /ssl/selfsigned.key;
     }

http3 效果(含升级过程)

2024-05-03-14-31-48.png

浏览器会有一个升级的过程,当前浏览器支持服务端的 h3 协议版本时就会将新的请求切换到 h3, 所以会出现部分 http2 部分 http3

2024-05-03-14-50-00.png

2024-05-03-16-18-20.png

http/2 与 3 性能对比

上面,请求100个请求看不出差距,加到 1000 请求数量后对比

http1

2024-05-03-16-44-38.png

没啥好说的,6 个连接一组,有连接复用请求排队情况

http2

2024-05-03-16-43-55.png

http2 因为复用连接,但只有一个连接,数据包分片返回,而且是无序的,所以请求量大时数据包会被插队,加上单连接窗口大小和容错性,使得请求时间被拉长

http3(升级完成后测试)

2024-05-03-16-45-52.png

http3 使用 UDP,没有连接阻塞所以.每个请求单独返回,大量并发时表现优秀

注意:

  1. 可能是 nginx 对 http3 支持是实验性的.所以偶尔会报错 ERR_QUIC_PROTOCOL_ERROR 后续请求就会降级,失败的请求不会自动重发

  2. 但是(巨坑!!!!) Alt-Svc 好像是独立工作的, 因为 Alt-Svc 设置了失效时间,当出现ERR_QUIC_PROTOCOL_ERROR导致降级,必须等待 Alt-Svc 过期才会去拿最新的 Alt-Svc,所以 Alt-Svc 失效时间别设置太长

  3. 每次 Alt-Svc 过期后都会进行一次降级再升级, http3 请求头中的 Alt-Svc 字段浏览器里好像无效,在 http2 和 http1 中有效

总结:

  1. http2 时在少量请求时相对于 http1 有一定提升.但并没有解决阻塞问题.在大量请求时还是会阻塞,并且单连接丢包会导致重发.使大量请求且网络环境不佳的情况下性能不及http1
  2. http3 使用 UDP 解决了阻塞问题,但不稳定.会出现反复降级,浏览器优先还是使用 TCP 保证兼容性,需要从 http1/2 升级到 http3,无法直接使用 http3