Chrome中HTTP/2请求停滞问题求助(Node.js+Express+SPDY环境)
这问题我之前帮团队排查过类似的,结合你的Node.js+Express+SPDY技术栈,Chrome独有的请求停滞大概率和几个常见的兼容性或配置问题有关,给你几个具体的排查和解决方向:
1. 优先替换SPDY为Node.js原生HTTP/2模块
SPDY是HTTP/2的前身,现在Node.js已经原生支持HTTP/2了,旧的SPDY库可能和新版Chrome的HTTP/2实现存在帧处理、流控制的兼容性bug,这是最容易踩的坑。
你可以尝试把SPDY替换成原生http2模块,代码示例如下:
const http2 = require('http2'); const express = require('express'); const fs = require('fs'); const app = express(); // 创建HTTP/2安全服务器 const server = http2.createSecureServer({ key: fs.readFileSync('你的私钥路径'), cert: fs.readFileSync('你的证书路径') }, app); // 后续的API路由配置不变 app.get('/api/xxx', (req, res) => { res.json({ data: 'xxx' }); }); server.listen(443);
如果替换后问题消失,基本可以确定是SPDY库的兼容性问题。
2. 调整HTTP/2流控制与窗口大小
Chrome对HTTP/2的初始窗口大小有默认限制,若你的服务器没有合理配置,并发请求或大体积响应时容易出现流阻塞。如果暂时不想替换SPDY,可以在SPDY配置里显式调整窗口大小和并发流数:
const spdy = require('spdy'); const server = spdy.createServer({ key: fs.readFileSync('你的私钥路径'), cert: fs.readFileSync('你的证书路径'), spdy: { windowSize: 32 * 1024 * 1024, // 32MB窗口大小,可根据业务调整 maxConcurrentStreams: 100 // 允许的最大并发流数量 } }, app);
同时确认你的API响应是否开启了分块传输(Transfer-Encoding: chunked),Express默认会处理,但如果手动禁用过,建议重新开启,避免大响应一次性传输导致阻塞。
3. 检查TLS配置的兼容性
Chrome对TLS版本和加密套件的要求比较严格,老旧的TLS配置可能导致HTTP/2协商异常,进而引发请求停滞。确保服务器启用TLS 1.2+,并使用Chrome支持的现代加密套件:
const constants = require('constants'); const server = spdy.createServer({ key: fs.readFileSync('你的私钥路径'), cert: fs.readFileSync('你的证书路径'), secureOptions: constants.SSL_OP_NO_TLSv1 | constants.SSL_OP_NO_TLSv1_1, // 禁用旧版TLS ciphers: 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384' }, app);
4. 利用HTTP2_SESSION日志定位具体问题
你手里的Chrome HTTP2_SESSION日志是关键,重点排查这几个点:
- 有没有
GOAWAY帧?如果有,查看附带的错误码(比如REFUSED_STREAM、INTERNAL_ERROR),直接定位服务器端的流处理问题。 - 停滞请求对应的流ID,是否卡在
WINDOW_UPDATE帧?这说明窗口大小不足,导致数据无法传输。 - 有没有
RST_STREAM帧?如果错误码是PROTOCOL_ERROR,说明存在协议层面的不兼容;如果是CANCEL则是客户端主动取消,但结合你的15-20秒停滞,前者概率更高。
5. 排查Express中间件的兼容性
部分Express中间件可能没有适配HTTP/2,比如某些日志、压缩中间件,在处理HTTP/2流时会出现阻塞。可以尝试逐步禁用中间件,观察问题是否消失,定位到具体中间件后,替换为兼容HTTP/2的版本或调整配置。
内容的提问来源于stack exchange,提问作者Marcus Longwell

