Node.js HTTP代理服务器出现Socket Hang Up错误排查
问题分析与解决方案
问题背景
容器化代理服务器(worker server)监听5000端口,启动时使用--network=host选项,无需端口映射即可访问主机端口。/get-buttons端点逻辑为:先执行shell脚本,再通过http-proxy将请求转发至主机6000端口的同端点。容器内执行curl localhost:6000/get-buttons可正常获取响应,但代理请求触发ECONNRESET(socket hang up)错误。
核心原因
异步执行shell脚本期间,Express的req(可读流)状态发生异常:默认情况下Express会持续读取请求流数据,等到异步脚本执行完成后再代理时,请求流可能已被耗尽或关闭,导致http-proxy无法正常转发请求,最终触发连接重置错误。
解决方案
方案1:暂停/恢复请求流
在异步执行脚本前暂停请求流,避免数据被提前消耗,代理操作前恢复流:
app.get('/get-buttons', (req, res) => { // 暂停请求流,防止数据被提前读取 req.pause(); exec(`sh hello_world.sh ${req.query.abc}`, (error, stdout, stderr) => { if (error) { console.error(`Error starting engine: ${error}`); res.status(500).send('Error executing shell script'); return; } console.log('Shell script executed successfully'); // 恢复请求流后执行代理 req.resume(); proxy.web(req, res, { target: 'http://localhost:6000/get-buttons' }, function (error) { console.log("Proxy Error ", error) }); }); });
方案2:同步执行脚本(适合短耗时脚本场景)
如果shell脚本执行速度快,可改用execSync同步执行,避免异步操作导致的请求流状态问题:
app.get('/get-buttons', (req, res) => { try { // 同步执行脚本 execSync(`sh hello_world.sh ${req.query.abc}`); console.log('Shell script executed successfully'); proxy.web(req, res, { target: 'http://localhost:6000/get-buttons' }, function (error) { console.log("Proxy Error ", error) }); } catch (error) { console.error(`Error starting engine: ${error}`); res.status(500).send('Error executing shell script'); return; } });
注意:同步执行会阻塞Node.js事件循环,高并发场景下不推荐使用。
方案3:优化http-proxy配置
添加changeOrigin和超时配置,确保代理请求的头部与连接状态正确:
const proxy = httpProxy.createProxyServer({ changeOrigin: true, timeout: 5000 // 根据实际业务调整超时时间 }); // 其余代码保持不变
验证
修改代码后重启容器,再次请求/get-buttons端点,确认代理请求正常返回响应,无ECONNRESET错误。
内容的提问来源于stack exchange,提问作者Jainta Paul
相关产品推荐
相关产品推荐

