首页 文章

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

提问于
浏览
2

场景

使用 node_redis 构建一个简单的Redis Pubish订阅(聊天)示例:https://github.com/nelsonic/hapi-socketio-redis-chat-example(与Hapi.js和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 回答

  • 2

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

    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();
    
  • 3

    问题是您的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')();
    
  • 1

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

    尝试定义另一个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

    redis-connection node.js模块

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

    Build Status

    Code Climate

    codecov.io

    Dependency Status

    devDependency Status

    代码很简单并经过测试,如果需要,可以处理 authentication . (不要在此复制粘贴模块以避免重复)
    见: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连接被缓存和重用)

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

相关问题