我的问题是,当我使用自定义http代理时,当响应管道发生错误时,套接字不会被释放。
看来Node.js并不是靠自己来做这个的。这就是为什么我试图通过销毁响应和底层套接字来自己发布它,但它没有工作。我尝试过的东西都没有,期望用agent.destroy()
摧毁一切。这显然不是解决方案,因为像这样正确运行的套接字正在被破坏。
这就引出了我的问题。释放套接字的正确方法是什么?
模仿一个例子来再现它。
node index.js
运行下面的脚本
如果你打电话给http://localhost:3000/small,你会看到我期望发生的行为。也就是说套接字被释放了。
const https = require("https");
const http = require("http");
const stream = require("stream");
const agent = new https.Agent({
maxSockets: 20,
maxFreeSockets: 10,
keepAlive: true,
keepAliveMsecs: 5000
});
const server = http.createServer((req, res) => {
let url = "https://releases.ubuntu.com/20.04.3/ubuntu-20.04.3-live-server-amd64.iso?_ga=2.138549238.47332115.1635229845-1229485524.1607530765";
if (req.url === "/small") {
url = "https://nodejs.org/dist/v14.18.1/node-v14.18.1-x64.msi";
}
https.get(url, {
agent
}, (stream) => {
stream.pipe(res);
}).on("error", (e) => {
console.error("Got error: " + e.message);
});
const cleanup = stream.finished(res, (error) => {
if (error) {
if (error.code === "ERR_STREAM_PREMATURE_CLOSE") {
console.error("Pipeline ended non gracefully with no explicit error");
// agent.destroy(); -- Don't want to do this!
res.socket.destroy();
res.destroy();
}
} else {
console.info("Stream succeeded.");
}
cleanup();
});
logSockets();
});
const getSocketCountPerHost = (socketGroup) => {
const regexp = /^:+|:+$/g;
const sockets = agent[socketGroup];
return Object.fromEntries(Object.entries(sockets).map(([key, value]) => [key.replace(regexp, ""), Array.isArray(value) ? value.length : value]));
}
const logSockets = () => {
const sockets = getSocketCountPerHost("sockets");
const freeSockets = getSocketCountPerHost("freeSockets");
console.info("httpsAgent.sockets", sockets);
console.info("httpsAgent.freeSockets", freeSockets);
};
server.listen(3000, () => {
console.log("Listening on port 3000");
setInterval(logSockets, 10_000)
});
前提条件:
发布于 2021-11-05 06:14:34
好的,我自己去拿。关键是从https.Agent
获取请求并在它过早关闭时销毁它。
const clientRequest = https.get(url, {
agent
}, (stream) => {
stream.pipe(res);
}).on("error", (e) => {
console.error("Got error: " + e.message);
});
const cleanup = stream.finished(res, (error) => {
if (error) {
if (error.code === "ERR_STREAM_PREMATURE_CLOSE") {
console.error("Pipeline ended non gracefully with no explicit error");
clientRequest.destroy();
}
} else {
console.info("Stream succeeded.");
}
cleanup();
});
https://stackoverflow.com/questions/69719460
复制相似问题