Node.js redis订阅内存泄漏

我是“服务器端JS”的新手,无法find一个长时间轮询与node.js和Redis-Sub的示例。

下面的代码运行良好,但今天我注意到内存使用量是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

“内存泄漏”来自代码client.on 。 你可以在请求/响应函数中调用它。 client.on是一个发射器(参见redis源码,index.js:111(截至今天的npm安装)),并定义了函数

将侦听器添加到指定事件的侦听器数组的末尾。 (Nodejs-Docs: 1 )

所以你不断地向客户端添加"message"function。 移动client.on在这个请求/响应 – “循环”之外,它应该停止“泄漏”。

像下面这样的东西在逻辑上是你要找的东西,所以从这里开始:

 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() ,但是除此之外还没有完成。 任何真正的内存泄漏将不得不从组件模块中引入。

对。 我想我现在明白这一点,但是如果我错了 ,请纠正我 :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可能会更好。

如果这样困扰你,你可以replaceres.end( JSON.stringify( lastMessage ) ); 如果你已经听说过redis,那么res.end( JSON.stringify( lastMessage ) ); ;;否则,在redis发送消息时设置一个处理程序来执行此操作。 该处理程序应该被设置为只运行一次,然后被删除; 你可以通过使用.once来代替.on