HTTP/2 与 HTTPS 结合下的性能优化实战

为什么 HTTP/2 必须搭配 HTTPS

HTTP/2 协议本身支持明文传输(h2c),但几乎所有主流浏览器都只实现基于 TLS 的 HTTP/2(h2)。这不是偶然——HTTP/2 的多路复用、头部压缩等特性在明文环境下容易受到中间人攻击和协议降级攻击。因此,部署 HTTP/2 的第一步就是确保 HTTPS 配置正确且高效

但 HTTPS 本身会引入 TLS 握手开销。如果配置不当,HTTP/2 的性能优势可能被 TLS 的额外延迟抵消。下面从协议层到服务器配置,逐步拆解优化要点。

一、TLS 层优化:为 HTTP/2 铺路

1. 启用 TLS 1.3

TLS 1.3 将握手从两次往返(2-RTT)压缩到一次往返(1-RTT),会话恢复时甚至可以实现 0-RTT。对于 HTTP/2 的多路复用场景,更快的握手意味着连接能更早进入数据传输阶段。

在 Nginx 中启用 TLS 1.3:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;

注意:TLS 1.3 下 ssl_ciphers 的配置不再生效,密码套件由 OpenSSL 自动协商。ssl_prefer_server_ciphers 建议设为 off,让客户端选择更优的套件。

2. 配置 OCSP Stapling

浏览器在 TLS 握手时需要验证服务器证书是否被吊销。传统方式是浏览器自己去访问 CA 的 OCSP 服务器,这会增加一个额外的网络请求。OCSP Stapling 让服务器在握手时直接附带吊销状态证明,省去这个往返。

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/chain.pem;
resolver 8.8.8.8 1.1.1.1 valid=300s;

3. 会话复用

TLS 会话复用可以跳过完整的握手过程。TLS 1.3 使用 PSK(预共享密钥)恢复,TLS 1.2 则依赖 Session ID 或 Session Ticket。在 Nginx 中:

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets on;

shared:SSL:10m 大约能存储 40000 个会话,对于大多数站点足够。

二、HTTP/2 层优化:发挥多路复用优势

1. 启用 HTTP/2

listen 443 ssl http2;

如果使用 Nginx 1.25.1 以上版本,推荐使用新语法:

listen 443 ssl;
http2 on;

2. 调整并发流与窗口大小

HTTP/2 的多路复用允许在同一连接上并行传输多个请求。但服务器对并发流数量有限制,窗口大小也会影响吞吐量。

http2_max_concurrent_streams 128;
http2_chunk_size 8k;

http2_max_concurrent_streams 默认值通常为 128,对于图片较多的站点可以适当提高。但注意:过高的并发流会消耗服务器内存,建议根据实际负载测试后调整。

3. 头部压缩与 HPACK

HTTP/2 使用 HPACK 算法压缩头部。虽然 Nginx 没有直接暴露 HPACK 的调优参数,但可以通过减少冗余头部来间接优化。例如:

  • 移除不必要的 X-Powered-ByServer 等头部
  • 避免在 Cookie 中存储过多数据(Cookie 会随每个请求发送)
  • 使用 http2_push_preload 配合 Link 头部实现资源推送

4. 服务器推送的取舍

HTTP/2 的 Server Push 曾被视为革命性特性,但实践表明它容易推送浏览器已缓存的资源,反而浪费带宽。Chrome 已在 106 版本后移除对 HTTP/2 Push 的支持。当前建议是:不要依赖 Server Push,改用 preload 提示。

add_header Link "</css/main.css>; rel=preload; as=style";
add_header Link "</js/app.js>; rel=preload; as=script";

三、连接层优化:减少握手次数

1. 启用 HSTS

HSTS(HTTP Strict Transport Security)强制浏览器使用 HTTPS,避免首次访问时的 HTTP 跳转。更重要的是,HSTS 允许浏览器缓存 HTTPS 状态,后续访问直接走 TLS。

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

max-age=63072000 表示两年。preload 标记可以申请加入浏览器预加载列表,但需谨慎——一旦加入,移除需要数月时间。

2. 使用 Alt-Svc 引导 HTTP/3

虽然本文聚焦 HTTP/2,但 HTTP/3 基于 QUIC 协议,在弱网环境下表现更好。可以通过 Alt-Svc 头部告知浏览器 HTTP/3 端点,实现平滑升级:

add_header Alt-Svc 'h3=":443"; ma=86400';

浏览器首次仍走 HTTP/2,后续请求尝试 HTTP/3。这不会影响现有 HTTP/2 连接的性能。

四、实战配置示例

以下是一个兼顾 HTTP/2 与 HTTPS 性能的 Nginx 配置片段:

server {
    listen 443 ssl;
    http2 on;
    server_name example.com;

    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets on;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /path/to/chain.pem;
    resolver 8.8.8.8 1.1.1.1 valid=300s;

    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
    add_header Alt-Svc 'h3=":443"; ma=86400';

    http2_max_concurrent_streams 128;
    http2_chunk_size 8k;

    location / {
        root /var/www/html;
        index index.html;
    }
}

五、验证与监控

配置完成后,用以下工具验证:

  • curlcurl -I --http2 https://example.com 查看是否返回 HTTP/2 200
  • Chrome DevTools:Network 面板中 Protocol 列显示 h2 即表示 HTTP/2 生效
  • SSL Labs:测试 TLS 配置评分,目标为 A 或 A+
  • WebPageTest:对比优化前后的首字节时间(TTFB)和开始渲染时间

监控方面,重点关注 TLS 握手时间、HTTP/2 流重置率、以及服务器 CPU 在 TLS 加解密上的开销。如果 CPU 成为瓶颈,可以考虑启用硬件加速或使用更高效的密码套件。

总结

HTTP/2 与 HTTPS 的结合不是简单的“开启开关”,而是一套从 TLS 握手到流控制的系统性优化。核心思路是:用 TLS 1.3 和会话复用降低握手成本,用合理的并发流和头部策略发挥多路复用优势,用 HSTS 和 Alt-Svc 减少连接建立的开销。每一步都需要根据实际流量特征测试调整,没有放之四海而皆准的参数。建议从 TLS 1.3 和 OCSP Stapling 入手,这两项改动风险低、收益明显,之后再逐步调优 HTTP/2 的流参数。

未经允许不得转载:任鹏个人博客 » HTTP/2 与 HTTPS 结合下的性能优化实战

赞 (0) 打赏

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏