You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ExpressJS HTTP Streaming 客户端断连后磁盘被占满问题

问题根因

磁盘空间被快速占满的核心原因是未捕获的流错误触发Node.js疯狂写入错误日志,和业务返回的随机字符串大小无关,具体触发逻辑:

  1. 客户端断开连接时,HTTP响应流会先抛出ECONNRESET(连接被对端重置)错误,原代码只监听了close事件,没有监听error事件,这个错误会变成未捕获异常,Node.js默认会把错误栈、缓冲区堆积数据持续写入磁盘日志/临时转储文件,这就是每秒百MB级写入的来源。
  2. 定时器逻辑完全忽略流状态:连接断开后res.write()会持续返回false(表示内核发送缓冲区已满,无法再向客户端发送数据),但定时器还是每秒往失效的流里塞数据,这些无效数据不断在缓冲区堆积,进一步放大了错误日志的写入量。
  3. 客户端代码存在缺陷:只调用了一次reader.read(),仅消费第一块数据后就不再处理后续流内容,哪怕不主动关闭页面,缓冲区很快就会被打满触发流异常。
修复方案

服务端调整

核心是补全流事件监听、处理背压、所有退出分支都做资源清理:

app.get('/data', (_, res) => {
    // 配置流式响应头
    res.setHeader('Content-Type', 'text/plain; charset=utf-8');
    res.setHeader('Cache-Control', 'no-cache');

    const interval = setInterval(() => {
        // 写入前判断流状态,流已结束就直接返回
        if (res.writableEnded) return;
        // 处理背压:write返回false表示缓冲区已满,等drain事件后再继续写入
        const canWrite = res.write(`${Math.random().toString()}\n`);
        if (!canWrite) {
            res.once('drain', () => {});
        }
    }, 1000);

    // 统一清理逻辑,所有终止场景都触发
    const cleanup = () => {
        clearInterval(interval);
        if (!res.writableEnded) {
            res.end();
        }
    };

    // 监听所有可能的流终止事件
    res.on('close', cleanup);
    res.on('finish', cleanup);
    res.on('error', (err) => {
        // 捕获连接错误,避免错误冒泡触发未捕获异常落盘
        console.error('客户端连接异常断开:', err.message);
        cleanup();
    });
});

额外建议在Node.js服务入口加全局错误捕获,兜底所有未处理的异常,避免异常触发系统级日志落盘:

process.on('uncaughtException', (err) => {
    console.error('全局未捕获异常:', err.message);
});
process.on('unhandledRejection', (reason) => {
    console.error('全局未处理Promise拒绝:', reason);
});

客户端调整

补全流循环读取逻辑,不要只读一次就停止消费:

const res = await fetch('/data')
const reader = res.body.getReader()
const decoder = new TextDecoder();

// 循环读取直到流结束
while (true) {
    const { value, done } = await reader.read();
    if (done) break;
    console.log(decoder.decode(value));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:57:27