You need to enable JavaScript to run this app. Node.js可写流writable stream挂起:大量写入后res.end()不执行请求挂起
优惠活动
大模型
产品
解决方案
定价
更多

Node.js可写流writable stream挂起:大量写入后res.end()不执行请求挂起

问题原因

1. 数据库连接池耗尽

pg-promise默认使用的连接池最大连接数为10,你代码中的双层循环单次请求要执行501 * 501 = 251001次独立SQL查询,当查询量超过连接池处理能力后,后续的await db.any()会进入无限等待队列,循环无法执行完毕,自然到不了res.end()的逻辑。
写入次数少的时候查询量很小,连接池足够支撑,循环可以快速走完,所以响应能正常结束。

2. HTTP响应背压未处理

res.write()方法会返回布尔值,当返回false时代表内核发送缓冲区已满,此时如果继续调用res.write(),写入的内容会全部缓存在Node.js进程内存中,随着内存占用持续升高,会导致进程响应变慢甚至卡住,进一步阻塞后续逻辑执行。

3. cork/uncork使用不合理

你每次调用res.write()前单独调用res.cork(),再通过process.nextTick()执行uncork(),这种写法相当于每次都强制缓冲单次写入的内容,反而降低了写入效率,加剧了内存堆积的风险。


解决方案

  • 优化数据库查询逻辑:不要在循环中执行单条查询,改用IN条件批量查询所需数据,大幅减少查询次数,从根源避免连接池耗尽。
  • 合理调整连接池参数:根据业务需要和PostgreSQL的最大连接限制,调整pg-promise的连接池大小,同时限制单次请求的查询并发数。
  • 处理HTTP响应背压:当res.write()返回false时,暂停循环和数据库查询,监听drain事件触发后再恢复执行,避免内存无限堆积。
  • 调整cork/uncork使用逻辑:不需要每次写入都单独加cork,对于连续的批量写入操作,可以统一cork后写入所有内容,再统一uncork提升写入效率。

内容的提问来源于stack exchange,提问作者disgustingtom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 03:57:04