I';我在集群node.js/socket.io/redis pub/sub应用程序中接收到重复消息
我使用Node.js、Socket.io和redistore、Socket.io的集群以及Redis 我有一个pub/sub应用程序,它只在一个Node.js节点上运行良好。但是,当它处于重负载时,它只会最大化服务器的一个核心,因为Node.js不是为多核机器编写的 正如您在下面看到的,我现在使用的是Learnboost的集群模块,也是制作Socket.io的人 但是,当我启动4个工作进程时,每个进入并订阅的浏览器客户端都会获得在Redis中发布的每条消息的4个副本。如果有三个工作进程,则有三个副本 我猜我需要以某种方式将redis pub/sub功能移动到cluster.js文件中 Cluster.jsI';我在集群node.js/socket.io/redis pub/sub应用程序中接收到重复消息,node.js,redis,socket.io,Node.js,Redis,Socket.io,我使用Node.js、Socket.io和redistore、Socket.io的集群以及Redis 我有一个pub/sub应用程序,它只在一个Node.js节点上运行良好。但是,当它处于重负载时,它只会最大化服务器的一个核心,因为Node.js不是为多核机器编写的 正如您在下面看到的,我现在使用的是Learnboost的集群模块,也是制作Socket.io的人 但是,当我启动4个工作进程时,每个进入并订阅的浏览器客户端都会获得在Redis中发布的每条消息的4个副本。如果有三个工作进程,则有三个
var cluster = require('./node_modules/cluster');
cluster('./app')
.set('workers', 4)
.use(cluster.logger('logs'))
.use(cluster.stats())
.use(cluster.pidfiles('pids'))
.use(cluster.cli())
.use(cluster.repl(8888))
.listen(8000);
redis = require('redis'),
sys = require('sys');
var rc = redis.createClient();
var path = require('path')
, connect = require('connect')
, app = connect.createServer(connect.static(path.join(__dirname, '../')));
// require the new redis store
var sio = require('socket.io')
, RedisStore = sio.RedisStore
, io = sio.listen(app);
io.set('store', new RedisStore);io.sockets.on('connection', function(socket) {
sys.log('ShowControl -- Socket connected: ' + socket.id);
socket.on('channel', function(ch) {
socket.join(ch)
sys.log('ShowControl -- ' + socket.id + ' joined channel: ' + ch);
});
socket.on('disconnect', function() {
console.log('ShowControll -- Socket disconnected: ' + socket.id);
});
});
rc.psubscribe('showcontrol_*');
rc.on('pmessage', function(pat, ch, msg) {
io.sockets.in(ch).emit('show_event', msg);
sys.log('ShowControl -- Publish sent to channel: ' + ch);
});
// cluster compatiblity
if (!module.parent) {
app.listen(process.argv[2] || 8081);
console.log('Listening on ', app.address());
} else {
module.exports = app;
}
App.js
var cluster = require('./node_modules/cluster');
cluster('./app')
.set('workers', 4)
.use(cluster.logger('logs'))
.use(cluster.stats())
.use(cluster.pidfiles('pids'))
.use(cluster.cli())
.use(cluster.repl(8888))
.listen(8000);
redis = require('redis'),
sys = require('sys');
var rc = redis.createClient();
var path = require('path')
, connect = require('connect')
, app = connect.createServer(connect.static(path.join(__dirname, '../')));
// require the new redis store
var sio = require('socket.io')
, RedisStore = sio.RedisStore
, io = sio.listen(app);
io.set('store', new RedisStore);io.sockets.on('connection', function(socket) {
sys.log('ShowControl -- Socket connected: ' + socket.id);
socket.on('channel', function(ch) {
socket.join(ch)
sys.log('ShowControl -- ' + socket.id + ' joined channel: ' + ch);
});
socket.on('disconnect', function() {
console.log('ShowControll -- Socket disconnected: ' + socket.id);
});
});
rc.psubscribe('showcontrol_*');
rc.on('pmessage', function(pat, ch, msg) {
io.sockets.in(ch).emit('show_event', msg);
sys.log('ShowControl -- Publish sent to channel: ' + ch);
});
// cluster compatiblity
if (!module.parent) {
app.listen(process.argv[2] || 8081);
console.log('Listening on ', app.address());
} else {
module.exports = app;
}
client.html
<script src="http://localhost:8000/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<script>
var socket = io.connect('localhost:8000');
socket.emit('channel', 'showcontrol_106');
socket.on('show_event', function (msg) {
console.log(msg);
$("body").append('<br/>' + msg);
});
</script>
var socket=io.connect('localhost:8000');
socket.emit('channel','showcontrol_106');
socket.on('show_event',函数(msg){
控制台日志(msg);
$(“正文”).append(“
”+msg);
});
我一直在与cluster和socket.io作斗争。每次我使用集群功能(尽管我使用内置的Nodejs集群),我都会遇到很多性能问题和socket.io的问题
在尝试研究这一点时,我一直在挖掘socket.io git上的bug报告和类似问题,任何使用集群或外部负载平衡器的服务器似乎都存在socket.io问题
它似乎产生了“客户端不握手客户端应该重新连接”的问题,如果增加详细日志记录,您将看到这个问题。每当socket.io在集群中运行时,就会出现这种情况,所以我认为它会恢复到这种状态。也就是说,客户机每次进行新连接时都会连接到socket.io集群中的随机实例(授权时会进行多个http/socket/flash连接,稍后轮询新数据时会进行更多连接)
现在我已经回复到一次只使用1个socket.io进程,这可能是一个bug,但也可能是socket.io构建方式的一个缺点
补充:我将来解决这个问题的方法是为集群内的每个socket.io实例分配一个唯一的端口,然后在客户端缓存端口选择。结果表明Node.js/socket.io没有问题,我只是用了完全错误的方法 我不仅从节点/套接字堆栈外部发布到Redis服务器,还直接订阅了Redis频道。在pub/sub情况的两端,我都绕过了“Socket.io集群,后端有Redis Store” 因此,我创建了一个小应用程序(使用Node.js/Socket.io/Express),它从我的Rails应用程序中获取消息,并使用Socket.io-announce模块将它们“宣布”到Socket.io房间中。现在,通过使用Socket.io路由魔术,每个节点工作者只会获取消息并将其发送到直接连接到他们的浏览器。换句话说,由于pub和sub都发生在Node.js/Socket.io堆栈中,因此不再有重复消息
在清理完代码后,我会在某个github上放一个示例 您可以看到我们在这里做了什么:但是,由于socket.io中的一个bug,我们将它回滚到单个节点。这里是一个关于这个bug的讨论,它现在可能已经被修复了:代码不在上面的GitHub链接中。你能在这里再次分享它吗?我面临着同样的问题。