Node.js redis订阅内存泄漏
我是“服务器端JS”的新手,找不到node.JS和Redis-Sub的长轮询示例 下面的代码运行得很好,但今天我注意到RAM的使用量是650MB,代码只运行了6天Node.js redis订阅内存泄漏,node.js,redis,Node.js,Redis,我是“服务器端JS”的新手,找不到node.JS和Redis-Sub的长轮询示例 下面的代码运行得很好,但今天我注意到RAM的使用量是650MB,代码只运行了6天 var http = require('http'), redis = require('redis'), client = redis.createClient(); client.subscribe("example"); http.createServer(function (req, re
var http = require('http'),
redis = require('redis'),
client = redis.createClient();
client.subscribe("example");
http.createServer(function (req, res) {
res.setHeader('Access-Control-Allow-Origin', 'https://mywebsite.com');
res.setHeader('Access-Control-Allow-Methods', 'GET');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
res.writeHead(200, {'Content-Type': 'application/json'});
client.on("message", function (channel, message) {
res.end( JSON.stringify( message ) );
});
}).listen(8080);
有人能指出内存泄漏并解释一下吗
我的node.js版本是:v0.10.21对。我想我现在明白了,但是如果我错了,请纠正我:redis客户端定期发送更新,准确地告诉它里面有什么数据。(因此,如果它从未更改,它将始终定期发送相同的消息。)使用当前代码,客户端可以向您的服务器发送请求,并接收redis服务器内容的更新。但是客户端将不得不等到下一次服务器从redis获得更新 客户必须等待的事实让人感觉不对劲。我认为它应该立即发送一个响应,其中包含从redis收到的上一次更新。只要稍加修改,这应该是可能的:
var http = require('http'),
redis = require('redis'),
client = redis.createClient();
var lastMessage = null;
client.subscribe("example");
client.on("message", function (channel, message) {
lastMessage = message
});
http.createServer(function (req, res) {
res.setHeader('Access-Control-Allow-Origin', 'https://mywebsite.com');
res.setHeader('Access-Control-Allow-Methods', 'GET');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
res.writeHead(200, {'Content-Type': 'application/json'});
res.end( JSON.stringify( lastMessage ) );
}).listen(8080);
而且上面的代码也不会重复设置redis处理程序,所以它不应该泄漏内存
我可以看到的一个缺点是,如果客户机在节点收到redis的消息之前请求更新,它将收到null
。在这种(可能不常见)情况下,最好先等redis回复
如果这让您感到困扰,您可以替换行res.end(JSON.stringify(lastMessage))代码>中有这样一句话:“如果您已经听到redis的消息,那么res.end(JSON.stringify(lastMessage));
;否则,在redis发送消息时设置一个处理程序来执行此操作”。处理程序应设置为仅运行一次,然后将其删除;您可能可以使用.once
而不是。on
上的“内存泄漏”来自code客户端。on
。您可以在请求/响应函数中调用它client.on
是一个发射器(请参阅redis source,index.js:111(从今天的npm安装开始)),它使用
将侦听器添加到指定事件的侦听器数组的末尾。(Nodejs文档:)
因此,您不断向客户端添加“message”
-函数。将客户端移动到该请求/响应之外的
“循环”中,它将停止“泄漏”。从逻辑上讲,您正在寻找以下内容,因此从这里开始:
var http = require('http'),
redis = require('redis'),
client = redis.createClient();
client.subscribe("example");
var responses = [];
client.on('message', function(channel, message) {
var res;
while (responses.length) {
res = responses.pop();
res.end(JSON.stringify(message));
}
});
http.createServer(function (req, res) {
res.setHeader('Access-Control-Allow-Origin', 'https://mywebsite.com');
res.setHeader('Access-Control-Allow-Methods', 'GET');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
res.writeHead(200, {'Content-Type': 'application/json'});
responses.push(res);
}).listen(8080);
当您继续收到尚未满足消息和end()
ed的请求时,您的内存需求将增加,但除此之外,这里并没有发生太多事情。任何真正的内存泄漏都必须从组件模块引入。每次服务器收到请求时,都会运行函数函数(req,res)
。每次运行时,client.on(“message”,…)
都会设置一个处理程序。这些处理器不会被移除;因此,每次收到请求时,内存使用都会增加。不仅如此,每次redis客户端收到消息时,都会运行函数函数(频道,消息)
。如果res
已经被发送,那么它可能不会做任何事情,但是如果有许多处理程序,那么这可能会导致很大的开销。(在这种情况下,你会看到处理每个请求的延迟。)结帐:你想做什么?我大致知道我认为它会起什么作用,但我看不出有任何合乎逻辑的理由这样做。客户端请求和redis数据之间的连接是什么?redis subscribe的工作原理类似于,您正在订阅通道并等待新消息。“我的代码”正在等待启用.on的新消息("消息,
功能。当一条新消息出现时,它会推送并关闭连接。我也这么认为。但我的观点是:对于您的代码版本,向您的服务器发送请求的客户端将不得不等到您的服务器下一次从redis收到消息。我假设这不是您想要的,所以我重写了它,以便服务器回复立即使用从redis收到的上一条消息。但是如果我错了,您确实想让客户端等待,那么请忽略我的回答,尝试将client.on(“message”,…)
更改为client.once(“message”,…)
。或者如果您需要其他内容,请详细说明。我使用客户端对其进行了负载测试。有一次
,它仍然线性增加(从45MB开始,达到80-85MB,GC下降到50MB,然后达到90-95MB,GC下降到60MB…)。您的负载测试是否包括来自redis的消息?如果没有,那么我预计会出现内存泄漏,因为处理程序仍然没有被删除。如果即使使用redis消息和,它也会泄漏内存。有一次,我没有解释。但我说的客户端在等待服务器获取redis消息时遇到延迟,对吗?H你试过按照我在回答中说的方式做吗?发生了什么?