如何实例化多个Redis连接以进行发布订阅(node.js + node_redis)

时间:2015-07-08 10:59:25

标签: node.js redis publish-subscribe hapijs node-redis

方案

使用 node_redis 构建一个简单的Redis Pubish订阅(聊天)示例:https://github.com/nelsonic/hapi-socketio-redis-chat-example with Hapi.js and Socket.io

我们在项目中创建了一个节点模块 redis_connection.js (参见:http://git.io/vqaos)来实例化Redis连接,因为我们不希望重复多次连接(到RedisCloud)的代码:

var redis = require('redis');
var url   = require('url');
var redisURL    = url.parse(process.env.REDISCLOUD_URL);
var redisClient = redis.createClient(redisURL.port, redisURL.hostname,
                  {no_ready_check: true});
redisClient.auth(redisURL.auth.split(":")[1]);

module.exports = redisClient;

然后我们使用这样:

var redisClient = require('./redis_connection.js');

// Confirm we are able to connect to  RedisCloud:
redisClient.set('redis', 'working', redisClient.print);
redisClient.get('redis', function (err, reply) {
  console.log('RedisCLOUD is ' +reply.toString());
});

这适用于Redis的正常GET / SET操作, 但是当我们尝试实例化Redis的多个连接时(例如:一个发布,另一个订阅,第三个只读GET / SET键/值)我们得到一个错误:

问题

我们看到以下错误:

Error: Connection in subscriber mode, only subscriber commands may be used

我们做错了什么?

我们发现此问题时的完整代码:http://git.io/vqa6y

注意

我们尝试来挖掘现有的SO Q / A,例如:

但未找到完全符合我们情况的解决方案......

任何建议/帮助非常感谢!

4 个答案:

答案 0 :(得分:3)

未经测试,但评论时间过长。

尝试定义另一个redis连接模块,一个用于常规用法,另一个用于pubsub订阅用途。

为您的项目添加redis_pubsub_connection.js

var redis = require('redis');
var url   = require('url');
var redisURL    = url.parse(process.env.REDISCLOUD_URL);
var redisPubSubClient = redis.createClient(redisURL.port, redisURL.hostname,
                  {no_ready_check: true});
redisPubSubClient.auth(redisURL.auth.split(":")[1]);

module.exports = redisPubSubClient;

将您的publish.js require语句更改为:

var redis = require('./redis_pubsub_connection'); // RedisCloud

答案 1 :(得分:2)

redis-connection node.js module

为了在我们的项目中保持可重用,我们编写了一个( mini )node.js模块来初始化Redis连接:https://github.com/dwyl/redis-connection < / p>

Build Status Code Climate codecov.io Dependency Status devDependency Status

代码简单且经过测试,如果需要,可以处理 身份验证 。 (不要在此复制粘贴模块以避免重复
见:https://github.com/dwyl/redis-connection/blob/master/index.js

用法:

从NPM安装

npm install redis-connection --save

在脚本中使用

var redisClient = require('redis-connection')();
redisClient.set('hello', 'world');
redisClient.get('hello', function (err, reply) {
  console.log('hello', reply.toString()); // hello world
});

发布订阅

var redisClient = require('redis-connection')(); // Publisher
var redisSub = require('redis-connection')('subscriber');
redisSub.subscribe("chat:messages:latest", "chat:people:new");

有关工作示例,请参阅:https://github.com/dwyl/hapi-socketio-redis-chat-example

优点是我们可以在同一个项目中的多个文件中重复使用相同的redisClient而无需创建新连接(单个或pub / sub连接被缓存并重新使用

信用:我们从几个地方借鉴了想法,所以已经投了所有答案。但最终我们编写了一个略有不同的解决方案,因此我们与NPM / GitHub上的所有人分享了它。再次感谢大家!

答案 2 :(得分:1)

问题是您的redis客户端创建代码正在被需要缓存,因此您可以反复使用相同的连接。您可以返回一个函数:

,而不是在redis_connection模块中返回连接
module.exports = function(){
    var redis = require('redis'); 
    var url = require('url'); var redisURL = url.parse(process.env.REDISCLOUD_URL); 
    var redisClient = redis.createClient(redisURL.port, redisURL.hostname, {no_ready_check: true});
    redisClient.auth(redisURL.auth.split(":")
    return redisClient;
}

然后这样称呼它:

var redisClient = require('./redis_connection.js')();

答案 3 :(得分:1)

如果您想提供常规连接和子连接,并且您希望确保在整个应用程序中只有一个连接,那么您可以使用包含单例概念的两个解决方案的组合,如下所示:

var subConnection, con;

var createConnection = module.exports.createConnection = function(){
    var redis = require('redis'); 
    var url = require('url'); var redisURL = url.parse(process.env.REDISCLOUD_URL); 
    var redisClient = redis.createClient(redisURL.port, redisURL.hostname, {no_ready_check: true});
    redisClient.auth(redisURL.auth.split(":")
    return redisClient;
}

module.exports.getSubConnection = function(){

if (!subConnection) 
    subConnection = createConnection();

return subConnection
}

module.exports.getConnection = function(){

if (!con) 
    con = createConnection();

return con
}

}

对其他两种连接类型重复,并将其称为

var con =  require('./redis_connection.js').getConnection();