Express中同一浏览器6次请求后POST请求积压的异常问题
问题描述
开发了一个处理POST请求耗时较长的应用,当同一浏览器在短时间(如5秒)内发送超过6次请求时,出现异常行为。
示例代码
服务端代码
app.options('/',cors({origin: "http://localhost:5050"})); app.post('/',cors({origin: "http://localhost:5050"}),async(req,res) => { console.log(Date.now()); await new Promise(resolve => setTimeout(resolve, 5000)); console.log("----complete----") res.send("Success"); })
客户端代码
$.ajax ({ url: "http://127.0.0.1:5050/", type: "POST", data: JSON.stringify({token:"62e2c285a01937cdb462985d"}), contentType: "application/json; charset=utf-8" }).done(function(result,status,xhr){ console.log("done");}
现象复现
当客户端在5秒内发送7次以上请求时,服务端输出(时间戳为毫秒级):
1659038307446 1659038307703 1659038307985 1659038308260 1659038308528 1659038308818 ----complete---- 1659038312459 ----complete---- 1659038312712 ----complete---- 1659038312994 ----complete---- 1659038313266 ----complete---- ----complete---- ----complete---- ----complete---- ----complete---- ----complete----
可见前6次请求日志间隔约0.3秒(对应手动点击按钮频率),但第6次与第7次日志间隔约5秒,显然Node.js要等第一个请求完成后才开始处理第7次请求。
补充发现:同一浏览器发送超6次请求后,换另一浏览器发送6次请求可立即得到处理,但同一浏览器的不同标签页不行。
疑问
- 该现象的原因是什么?
- 为何限制是6次?
- 是否可以修改该行为?
问题解答
1. 现象原因
这不是Express或Node.js的限流机制,而是浏览器本身对同一域名下的并发HTTP请求数做了限制。浏览器会为同一个域名建立的TCP连接数设置上限,超出上限的请求会被放入队列,等待已有连接释放后再发送到服务端。
你的服务端每个请求耗时5秒,前6次请求占用了浏览器允许的所有并发连接,第7次请求只能等第一个连接处理完成、释放后才能被发送,所以服务端要等5秒才会收到第7次请求的日志。
2. 为什么是6次?
这个并发连接数限制是浏览器的默认配置,不同浏览器的默认值略有差异:
- Chrome、Firefox等现代浏览器的默认同一域名并发连接数为6
- 部分旧版浏览器的默认值为4
你遇到的6次正是Chrome/Firefox这类主流浏览器的默认上限。
3. 如何修改该行为?
客户端侧优化
- 域名分片:将请求分散到多个子域名(如
api1.example.com、api2.example.com),每个域名都能享受独立的并发连接上限,从而提升整体并发数。 - 使用HTTP/2:HTTP/2支持在同一个TCP连接上多路复用多个请求,不受传统的并发连接数限制,只要服务端支持HTTP/2,就能突破这个瓶颈。
服务端侧优化
- 启用HTTP/2:Express可以通过Node.js原生的
http2模块或第三方库(如spdy)支持HTTP/2,这样浏览器就能在单个连接上发送多个请求,无需等待连接释放。 - 无需调整Express核心配置:因为问题根源在浏览器层面,修改Express本身无法解决该限制。
内容的提问来源于stack exchange,提问作者Dominic Johnston Whiteley
相关产品推荐
相关产品推荐

