我是“Server-Side 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, 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
答案 0 :(得分:2)
“内存泄漏”来自代码client.on
。你在请求/响应函数中调用它。 client.on
是一个发射器(请参阅redis源,index.js:111(截至今天的npm安装))并使用
on
将侦听器添加到指定事件的侦听器数组的末尾。 (Nodejs-Docs:1)
所以你不断向客户端添加"message"
- 函数。将client.on
移到此请求/响应 - “循环”之外,它应该停止“泄漏”。
答案 1 :(得分:1)
以下内容在逻辑上符合您的要求,请从此处开始:
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的请求时,您的内存需求将会增长,但除此之外,此处不会发生很多事情。任何真正的内存泄漏都必须从组件模块中引入。
答案 2 :(得分:0)
右。我想我现在明白了这一点,但纠正我,如果我错了: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
来完成此操作。