Node.js使用http-proxy结合http Agent出现文件描述符泄漏问题
WebSocket代理套接字泄漏问题排查与疑问
问题现象
使用http-proxy搭建的WebSocket代理运行正常,但在每秒100-300次请求的高并发场景下,进程启动一段时间后出现大量开放套接字泄漏。
执行lsof -p 16可看到大量TCPv6套接字:
node 16 root 254u sock 0,9 0t0 390707607 protocol: TCPv6 node 16 root 256u sock 0,9 0t0 390351892 protocol: TCPv6 node 16 root 262u sock 0,9 0t0 390313109 protocol: TCPv6
查看/proc目录也能看到这些套接字:
ls -haltr /proc/16/fd lrwx------ 1 root root 64 Dec 22 16:22 367 -> 'socket:[390186932]'
已尝试的无效方案
- 为http Agent配置
maxFreeSockets、timeout等参数 - 应用相关修复补丁
- 将Agent的
keepAlive设为false
以上操作均未解决套接字泄漏问题。
代理代码示例
import Proxy from "http-proxy"; import http from "http"; import type { IncomingMessage, ClientRequest } from "http"; function create(): Proxy { const agent = new http.Agent({ keepAlive: true, maxSockets: Infinity, keepAliveMsecs: 1000, scheduling: "fifo", maxFreeSockets: 10, timeout: 300 * 1000 }); const proxy = Proxy.createProxyServer({ timeout: 300 * 1000, proxyTimeout: 300 * 1000, agent }); function proxyReqHandler(proxyReq: ClientRequest, req: IncomingMessage): void { proxyReq.setHeader("Content-Type", req.headers["content-type"] || "plain/text"); } proxy.on("proxyReq", proxyReqHandler); return proxy; } export function proxyWs(urlPath: string) { const proxy = create(); return function (req, socket, upgradeHead, params) { const targetUrl = ... // some logic to create target url const socketFd = (socket as any)?._handle?.fd; proxy.ws(req, socket, upgradeHead, { target: targetUrl, ignorePath: true }, err => { tracer.error(`error: ${err.message}`); }); }; }
后续发现(更新)
添加日志后观察到,挂起的套接字未触发end事件,推测是客户端未发送关闭事件导致套接字长期挂起。但此前已配置超时参数,原本期望超时能自动关闭这些套接字,疑问:为何套接字超时未生效?
内容的提问来源于stack exchange,提问作者Rostislav Shtanko
相关产品推荐
相关产品推荐

