扩展socket.io应用程序的方法有哪些?我看到以下问题,我不明白如何解决:
我很难想象它应该如何运作 - 也许是所有必要信息的共享变体商店,例如redis - 这是否可能?
编辑:我发现了这篇文章:http://www.ranu.com.ar/2011/11/redisstore-and-rooms-with-socketio.html基于此,我做了以下几点:
var pub = redis.createClient();
var sub = redis.createClient();
var store = redis.createClient();
pub.auth("pass");
sub.auth("pass");
store.auth("pass");
io.configure( function(){
io.enable('browser client minification'); // send minified client
io.enable('browser client etag'); // apply etag caching logic based on version number
io.enable('browser client gzip'); // gzip the file
io.set('log level', 1); // reduce logging
io.set('transports', [ // enable all transports (optional if you want flashsocket)
'websocket'
, 'flashsocket'
, 'htmlfile'
, 'xhr-polling'
, 'jsonp-polling'
]);
var RedisStore = require('socket.io/lib/stores/redis');
io.set('store', new RedisStore({redisPub:pub, redisSub:sub, redisClient:store}));
});
但是我收到以下错误:
Error: Uncaught, unspecified 'error' event.
at RedisClient.emit (events.js:50:15)
at Command.callback (/home/qwe/chat/io2/node_modules/socket.io/node_modules/redis/index.js:232:29)
at RedisClient.return_error (/home/qwe/chat/io2/node_modules/socket.io/node_modules/redis/index.js:382:25)
at RedisReplyParser.<anonymous> (/home/qwe/chat/io2/node_modules/socket.io/node_modules/redis/index.js:78:14)
at RedisReplyParser.emit (events.js:67:17)
at RedisReplyParser.send_error ( /home/qwe/chat/io2/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js:265:14)
at RedisReplyParser.execute (/home/qwe/chat/io2/node_modules/socket.io/node_modules/redis/lib/parser/javascript.js:124:22)
at RedisClient.on_data (/home/qwe/chat/io2/node_modules/socket.io/node_modules/redis/index.js:358:27)
at Socket.<anonymous> (/home/qwe/chat/io2/node_modules/socket.io/node_modules/redis/index.js:93:14)
at Socket.emit (events.js:67:17)
我的Redis凭据绝对正确。
编辑:非常奇怪,但禁用Redis授权,一切正常。所以这个问题仍然有效。另外,我有一个关于如何在此RedisStorage模式下为组(房间)的所有参与者获取信息(例如用户名)的问题,是否可以实现此功能?理想情况下,这可以通过Redis Pub / Sub功能完成。答案 0 :(得分:0)
您可以使用socket.io群集来实现此功能 https://github.com/muchmala/socket.io-cluster
答案 1 :(得分:0)
尝试添加此代码;
pub.on('error', function (err) {
console.error('pub', err.stack);
});
sub.on('error', function (err) {
console.error('sub', err.stack);
});
store.on('error', function (err) {
console.error('store', err.stack);
});
它不会修复它,但它至少应该给你一个更有用的错误。
答案 2 :(得分:0)
我建议你不要使用RedisStore。它有一个CPU使用问题,因为它使用pub-sub很差导致不可扩展(它可以接收少于一个纯socket.io的实例与socket.io的负载相当无用)。我个人使用Redis作为数据存储来保存房间列表并实现我自己的房间功能(Redis是内存中的键值数据库,但具有持久性机制)。当你想要房间数据时,只需从相同的redis中获取数据即可。但是,为了能够在多个实例中运行Socket.io,您还需要像HAProxy,Nginx这样的负载均衡器将工作分离到多个node.js端口,否则,您的用户仍将只使用一个node.js进程。这是一项巨大的工作。如果你还有其他语言的其他网络前端,那也更有效,因为有些网络会阻止除端口80和443之外的所有端口。您可以在以下网址阅读有关这些内容的更多信息:
答案 3 :(得分:0)
另一种可能的解决方案是使用像PubNub这样的替代方案来扩展实时交互。我在开发Mote.io时遇到了类似的问题,并决定采用托管解决方案而不是构建负载均衡器。我现在为PubNub工作。
PubNub将处理您正在讨论的数据同步问题。通常,您需要跨服务器同步redis或将客户端负载平衡到同一实例,以确保它们获得所有相同的消息。 PubNub抽象了这个,所以你不必担心它。
Enter Chat and press enter
<div><input id=input placeholder=you-chat-here /></div>
Chat Output
<div id=box></div>
<script src=http://cdn.pubnub.com/pubnub.min.js></script>
<script>(function(){
var box = PUBNUB.$('box'), input = PUBNUB.$('input'), channel = 'chat';
PUBNUB.subscribe({
channel : channel,
callback : function(text) { box.innerHTML = (''+text).replace( /[<>]/g, '' ) + '<br>' + box.innerHTML }
});
PUBNUB.bind( 'keyup', input, function(e) {
(e.keyCode || e.charCode) === 13 && PUBNUB.publish({
channel : channel, message : input.value, x : (input.value='')
})
} )
})()</script>
答案 4 :(得分:0)
我使用rabbitMQ实现了socket.io
应用程序扩展。在我当前的设置中,我在docker swarm中运行了两个socket.io应用程序容器的副本并与它们通信。这是每个消息显示的带有容器ID的演示:
RabbitMQ是一个消息代理,基本上,它同步应用程序后端的所有实例。后端的每个实例都将其消息推送到rabbitMQ上的队列,该队列由所有其他实例使用。 NodeJS中的RabbitMQ处理程序如下所示。
function rabbitHandler(io){
rabbitMQHandler('amqp://test_rabbit', function(err, options){
if(err){
throw err;
}
options.onMessageReceived = onMessageReceived;
io.on('connection', websocketConnect);
function websocketConnect(socket){
console.log('New connection')
io.emit('start', {ipHost: os.hostname()})
socket.on('disconnect', socketDisconnect);
socket.on('message', socketMessage);
function socketDisconnect(e){
console.log('Disconnect ', e);
}
function socketMessage(text){
var message = {text: text, date: new Date(), ip: os.hostname()};
// io.emit('message', message) // Instead of emitting the message on socket, it is being pushed on rabbitMQ queue.
options.emitMessage(message);
}
}
function onMessageReceived(message){
io.emit('message', message)
}
});
}
套接字客户端没有任何变化。
整个项目在以下链接中给出了docker image和docker compose文件。你可以尝试一下。