Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js redis订阅内存泄漏_Node.js_Redis - Fatal编程技术网

Node.js redis订阅内存泄漏

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

我是“服务器端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

对。我想我现在明白了,但是如果我错了,请纠正我: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你试过按照我在回答中说的方式做吗?发生了什么?