如何为发布订阅实例化多个 Redis 连接 (node.js + node_redis)
How to instantiate Multiple Redis Connections for Publish Subscribe (node.js + node_redis)
场景
使用node_redis构建一个简单的Redis发布订阅(聊天)示例: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());
});
这适用于正常的 GET/SET Redis 操作,
但是当我们尝试实例化到 Redis 的多个连接时(例如:一个用于发布,另一个用于订阅,第三个仅用于 GET/SET keys/values),我们得到一个错误:
问题
我们看到以下错误:
Error: Connection in subscriber mode, only subscriber commands may be used
我们做错了什么?
我们看到此问题时的完整代码:http://git.io/vqa6y
备注
我们尝试挖掘现有的 SO Q/A,例如:
- Publish subscribe with nodejs and redis(node_redis)
- Redis publish/subscribe: see what channels are currently subscribed to
- how to use the redis publish/subscribe
但没有找到完全符合我们情况的解决方案...
(任何suggestions/help非常感谢!)
问题是您的 redis 客户端创建代码正在被 requires 缓存,因此您一次又一次地重复使用相同的连接。您可以 return 一个函数,而不是 return 在您的 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')();
未测试,但评论时间太长。
尝试定义另一个 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
要求语句更改为:
var redis = require('./redis_pubsub_connection'); // RedisCloud
如果你想提供常规连接和子连接,并且你想确保你在整个应用程序中只有一个,那么你可以使用包括单例概念的两种解决方案的组合,比如这个:
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();
redis-连接node.js模块
为了在我们的项目中保持这个可重复使用,我们编写了一个 (mini) node.js 模块来初始化 Redis 连接:https://github.com/dwyl/redis-connection
代码简单且经过测试,并在需要时负责身份验证。
(不要在此处复制粘贴模块以避免重复)
参见: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 上与大家分享了它。再次感谢大家!
场景
使用node_redis构建一个简单的Redis发布订阅(聊天)示例: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());
});
这适用于正常的 GET/SET Redis 操作, 但是当我们尝试实例化到 Redis 的多个连接时(例如:一个用于发布,另一个用于订阅,第三个仅用于 GET/SET keys/values),我们得到一个错误:
问题
我们看到以下错误:
Error: Connection in subscriber mode, only subscriber commands may be used
我们做错了什么?
我们看到此问题时的完整代码:http://git.io/vqa6y
备注
我们尝试挖掘现有的 SO Q/A,例如:
- Publish subscribe with nodejs and redis(node_redis)
- Redis publish/subscribe: see what channels are currently subscribed to
- how to use the redis publish/subscribe
但没有找到完全符合我们情况的解决方案...
(任何suggestions/help非常感谢!)
问题是您的 redis 客户端创建代码正在被 requires 缓存,因此您一次又一次地重复使用相同的连接。您可以 return 一个函数,而不是 return 在您的 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')();
未测试,但评论时间太长。
尝试定义另一个 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
要求语句更改为:
var redis = require('./redis_pubsub_connection'); // RedisCloud
如果你想提供常规连接和子连接,并且你想确保你在整个应用程序中只有一个,那么你可以使用包括单例概念的两种解决方案的组合,比如这个:
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();
redis-连接node.js模块
为了在我们的项目中保持这个可重复使用,我们编写了一个 (mini) node.js 模块来初始化 Redis 连接:https://github.com/dwyl/redis-connection
代码简单且经过测试,并在需要时负责身份验证。
(不要在此处复制粘贴模块以避免重复)
参见: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 上与大家分享了它。再次感谢大家!