创见博客
项目如何从http1.1升级到http2.x
七崽爱吃小饼干2026/09/25阅读 0

在对创见首页进行 Lighthouse 性能分析的时候,发现网站用的是 HTTP/1.1,性能不佳。

Lighthouse 的建议里也直接点出了这个问题——升级到现代 HTTP 协议能显著提升资源加载效率。

HTTP/1.1 和新协议有什么不同

要理解为什么值得升级,先看这几个版本的核心差异。

HTTP/1.1(1997 年)是最经典的一版,它的问题主要有:

  • 队头阻塞:同一条 TCP 连接上,请求必须按顺序返回,前一个慢会拖住后面所有请求。
  • 并发连接数受限:浏览器对同一域名一般只开 6 个 TCP 连接,超出的请求要排队。
  • 头部冗余且不压缩:每次请求都带完整头部(Cookie、User-Agent 等),重复传输浪费带宽。
  • 文本协议:报文是纯文本,解析效率低。

HTTP/2(2015 年)做了几件关键的事:

  • 二进制分帧:把请求/响应拆成带编号的帧,收发更高效。
  • 多路复用:一条 TCP 连接上并行跑多个请求,从应用层解决了队头阻塞。
  • 头部压缩(HPACK):用索引表压缩重复的头部字段。
  • 服务器推送:服务器可以主动推送资源(实践中用得不多)。

HTTP/3(2022 年)更进一步,把底层传输从 TCP 换成了基于 UDP 的 QUIC:

  • 从根本上解决了 TCP 层的队头阻塞(HTTP/2 仍会受此影响)。
  • 0-RTT 建连,重连更快。
  • 支持连接迁移,弱网切换网络时不断连。

我们的需求是快速见效,所以先从 HTTP/1.1 升到 HTTP/2——这也是 Nginx 改一行配置就能搞定的。

为什么改的是 Nginx,而不是代码

HTTP/2 是在 TLS 握手阶段通过 ALPN 协商出来的传输层协议,跟应用代码无关。我们的架构是:

text
浏览器 --(HTTPS / ALPN)--> Nginx --(HTTP/1.1)--> Next.js :3000

浏览器到 Nginx 这一段走 HTTP/2,Nginx 到 Next.js 的内部代理仍然走 HTTP/1.1,应用代码完全不用动。

原来的 Nginx 配置

打开站点配置,可以看到 443 的 server 块写的是 listen 443 ssl;:

nginx
server {
    listen 443 ssl; # managed by Certbot
    server_name visionaryblog.cn;

    ssl_certificate /etc/letsencrypt/live/visionaryblog.cn/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/visionaryblog.cn/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
    }
}

listen 443 ssl 只启用了 HTTPS,并没有开启 HTTP/2。

修改配置

把 listen 443 ssl; 改成 listen 443 ssl http2; 即可:

nginx
listen 443 ssl http2;

两个 server 块(www.visionaryblog.cn 的跳转块和主站块)都要改。

注意:Nginx 1.25.1+ 官方推荐用独立的 http2 on; 指令替代 listen ... http2 的写法,但 1.24 及更早版本仍然用 listen 443 ssl http2。

校验并生效

改配置前先备份,再校验语法,最后重载:

bash
sudo cp /etc/nginx/sites-enabled/nextjs-app /root/nextjs-app.conf.bak
sudo nginx -t
sudo systemctl reload nginx

等 nginx -t 输出 syntax is ok 之后再 reload。reload 是平滑重载,不会中断现有连接,比 restart 更安全。

验证是否生效

用 curl 查看实际协商到的协议版本:

bash
curl -s -o /dev/null -w "%{http_version}\n" --http2 https://visionaryblog.cn/
# 2

返回 2 就说明 HTTP/2 生效了。也可以强制用 HTTP/1.1 请求做对比:

bash
curl -s -o /dev/null -w "%{http_version}\n" --http1.1 https://visionaryblog.cn/
# 1.1

需要注意,浏览器只在 HTTPS 下才支持 HTTP/2(明文的 h2c 模式浏览器基本不支持),所以这个升级只适用于已经配好证书的站点。

重新用 Lighthouse 验证

改完之后重新跑一次 Lighthouse,「使用 HTTP/2」这一项已经通过检查:

小结

  • HTTP/1.1 → HTTP/2 的收益主要是多路复用、头部压缩、二进制分帧,能明显减少资源加载的排队。
  • 升级只改 Nginx 一行配置:listen 443 ssl; → listen 443 ssl http2;,应用代码零改动。
  • 流程:备份 → 改配置 → nginx -t → reload → curl 验证。
  • 想再进一步可以上 HTTP/3,但需要 Nginx 编译 QUIC 模块(1.25+),配置更复杂,可以后续再做。
评论
0/100