Permalink
Browse files

複数台構成でSocket.ioのコネクションがうまく張られない時がある不具合を修正

  • Loading branch information...
1 parent c5bc425 commit b5682db8d31ec1b743825b05b30f3f67116492e7 @nsyee nsyee committed Nov 12, 2012
Showing with 131 additions and 62 deletions.
  1. +48 −39 app.js
  2. +78 −18 lib/controllers/socketIo.js
  3. +2 −2 public/js/chatroomApp.js
  4. +2 −2 public/js/dist/chatroom.js
  5. +1 −1 public/js/dist/chatroom.min.js
View
87 app.js
@@ -17,10 +17,10 @@ var TwitterStrategy = require('passport-twitter').Strategy;
// 複数ページにまたがる場合のエラーメッセージ等の一時的保管
// 出力したら消えてくれる
var flash = require('connect-flash');
-var cookieLib = require('cookie'); // cookie 操作npmモジュール
var log4js = require('log4js'); // ログ出力モジュール
var stackTrace = require('stack-trace'); // エラーobjectの追跡とか
var emailjs = require('emailjs/email');
+var cookieLib = require('cookie'); // cookie 操作npmモジュール
// セッションをRedisに保持
var RedisStore = require('connect-redis')(express);
var sessionStore = new RedisStore({
@@ -29,6 +29,7 @@ var sessionStore = new RedisStore({
db: 1,
prefix: 'session:'
});
+app.set('sessionStore', sessionStore);
// マルチプロセス/サーバー間でSocket.IOのセッションをRedisを使って共有する
var redis = require('socket.io/node_modules/redis');
var SocketIoRedisStore = require('socket.io/lib/stores/redis');
@@ -280,45 +281,53 @@ io.configure(function() {
redisSub: ioSub,
redisClient: ioStore
}));
-
- io.set('authorization', function(handshake, callback) {
- logger.info('##socket.io authorization');
-
- var chatroomId = handshake.query.id;
- var isUrlOpen = handshake.query.urlopen;
- var namespace;
- if (isUrlOpen) {
- namespace = '/chatrooms/'+chatroomId+'/open';
- }
- else {
- namespace = '/chatrooms/'+chatroomId;
- }
-
- if (!io.namespaces.hasOwnProperty(namespace)) {
- var chatroom = io.of(namespace);
- // ioConnect の確定
- chatroom.on('connection', socketIoController.onConnection);
- }
-
- // ExpressとSocket.io間でセッションを共有
- if (handshake.headers.cookie) {
- var cookie = handshake.headers.cookie;
- var sessionId = cookieLib.parse(cookie)['sess_id'];
- sessionId = sessionId.split(':')[1].split('.')[0];
-
- sessionStore.get(sessionId, function(err, session) {
- if (err) {
- callback(err.message, false);
- }
- else {
- handshake.session = session;
- }
- });
- }
-
- callback(null, true);
- });
+ io.sockets.on('connection', socketIoController.onConnection);
+ io.sockets.on('disconnect', socketIoController.onDisconnect);
+
+ /**************
+ RedisStoreを使っているときにauthorizationの中でconnectionを設定しようとすると、断続的に接続できない現象が起きている。
+ そのため、認証フェーズでconnectionの設定やネームスペースの作成、セッションの共有を行うのを取り止めることにする(本来はここでやるべき)。
+ ***************/
+
+ // io.set('authorization', function(handshake, callback) {
+ // logger.info('##socket.io authorization');
+
+ // var chatroomId = handshake.query.id;
+ // var isUrlOpen = handshake.query.urlopen;
+ // var namespace;
+ // if (isUrlOpen) {
+ // namespace = '/chatrooms/'+chatroomId+'/open';
+ // }
+ // else {
+ // namespace = '/chatrooms/'+chatroomId;
+ // }
+
+ // if (!io.namespaces.hasOwnProperty(namespace)) {
+ // var chatroom = io.of(namespace);
+ // // ioConnect の確定
+ // chatroom.on('connection', socketIoController.onConnection);
+ // }
+
+ // // ExpressとSocket.io間でセッションを共有
+ // if (handshake.headers.cookie) {
+ // var cookie = handshake.headers.cookie;
+ // var sessionId = cookieLib.parse(cookie)['sess_id'];
+ // sessionId = sessionId.split(':')[1].split('.')[0];
+
+ // sessionStore.get(sessionId, function(err, session) {
+ // if (err) {
+ // callback(err.message, false);
+ // }
+ // else {
+ // handshake.session = session;
+ // }
+ // });
+ // }
+
+ // callback(null, true);
+ // });
});
+app.set('io', io);
/************ /Socket.IO ************/
@@ -1,29 +1,26 @@
var app = require('../../app');
+var config = require('config');
var Chatroom = require('../models/chatroom').Chatroom;
var Chat = require('../models/chat').Chat;
var CONST = require('../const').CONST;
var utils = require('../utils');
var check = require('validator').check;
+var cookieLib = require('cookie'); // cookie 操作npmモジュール
+var redis = require('socket.io/node_modules/redis');
+var redisClient = redis.createClient(config.redis.port, config.redis.host);
var ownerClients = {}; //ハウスオーナーのSocket.ioのセッションを保持
exports.onConnection = function(socket) {
var logger = app.set('logger');
- logger.info('##socket.io: connection');
-
- var user;
- var _csrf;
-
- if (socket.handshake.session) {
- user = socket.handshake.session.passport.user;
- _csrf = socket.handshake.session._csrf;
- }
+ var sessionStore = app.set('sessionStore');
var chatroomId = socket.handshake.query.id;
var isUrlOpen = socket.handshake.query.urlopen;
+ var user;
+ var _csrf;
- //未ログイン時は以降の処理を行わない
-// if (!user) { return; }
+ logger.info('##socket.io: connection');
//validation
try {
@@ -33,6 +30,28 @@ exports.onConnection = function(socket) {
return;
}
+ //部屋に接続してきたユーザーのセッションIDを部屋ごとに保持
+ //## Socket.ioのnamespaceの独自実装
+ redisClient.hset("chatroomClients", socket.id, "true");
+
+
+ // // ExpressとSocket.io間でセッションを共有
+ if (socket.handshake.headers.cookie) {
+ var cookie = socket.handshake.headers.cookie;
+ var sessionId = cookieLib.parse(cookie)['sess_id'];
+ sessionId = sessionId.split(':')[1].split('.')[0];
+
+ sessionStore.get(sessionId, function(err, session) {
+ if (err) { logger.error(err); return; }
+
+ if (session) {
+ user = session.passport.user;
+ _csrf = session._csrf;
+ }
+ });
+ }
+
+
// 招待機能を使わないため一時コメントアウト
// Chatroom.findOneById(chatroomId, function(err, chatroom) {
// if (err) { logger.error(err); return; }
@@ -45,6 +64,10 @@ exports.onConnection = function(socket) {
socket.on('message', function(data) {
logger.info('##socket.io: message');
+
+ //未ログイン時は以降の処理を行わない
+ if (!user) { return; }
+
//CSRF Check
if (_csrf && _csrf !== data.token) {
logger.error('CSRF Invalid');
@@ -69,7 +92,7 @@ exports.onConnection = function(socket) {
Chatroom.findOneById(data.chatroomId, function(err, chatroom) {
if (err) { logger.error(err); return; }
- data.userId = user ? user.id : data.userId;
+ data.userId = user.id;
data.ownerId = chatroom.ownerId;
if (data.mode === 'create') {
@@ -93,6 +116,8 @@ exports.onConnection = function(socket) {
};
function createEntry(socket, data) {
+ var io = app.set('io');
+
Chat.create({
chatroomId: data.chatroomId,
userId: data.userId,
@@ -109,10 +134,18 @@ function createEntry(socket, data) {
var user = socket.handshake.session.passport.user;
var isUrlOpen = socket.handshake.query.urlopen;
+
//オーナーの発言はブロードキャスト
if (user && (user.id === data.ownerId)) {
- socket.emit('message', data);
- socket.broadcast.emit('message', data);
+ //socket.emit('message', data);
+ //socket.broadcast.emit('message', data);
+ redisClient.hkeys("chatroomClients", function(err, clients) {
+ clients.forEach(function(sid) {
+ process.nextTick(function() {
+ io.sockets.socket(sid).emit('message', data);
+ });
+ });
+ });
}
else {
//参加申請での申込者の発言はオーナーと申込者本人のみにemit
@@ -127,6 +160,8 @@ function createEntry(socket, data) {
}
function createChat(socket, data) {
+ var io = app.set('io');
+
Chat.create({
chatroomId: data.chatroomId,
userId: data.userId,
@@ -140,12 +175,20 @@ function createChat(socket, data) {
data.time = results[0].time;
data.message = utils.nl2br(utils.escHtml(data.message));
- socket.emit('message', data);
- socket.broadcast.emit('message', data);
+ //socket.emit('message', data);
+ //socket.broadcast.emit('message', data);
+ redisClient.hkeys("chatroomClients", function(err, clients) {
+ clients.forEach(function(sid) {
+ process.nextTick(function() {
+ io.sockets.socket(sid).emit('message', data);
+ });
+ });
+ });
});
}
function destroy(socket, data) {
+ var io = app.set('io');
var chatId = data.chatId;
//validation
@@ -166,9 +209,26 @@ function destroy(socket, data) {
if (err2) { logger.error(err2); return; }
data.chatId = chatId;
- socket.emit('message', data);
- socket.broadcast.emit('message', data);
+ //socket.emit('message', data);
+ //socket.broadcast.emit('message', data);
+ redisClient.hkeys("chatroomClients", function(err, clients) {
+ clients.forEach(function(sid) {
+ process.nextTick(function() {
+ io.sockets.socket(sid).emit('message', data);
+ });
+ });
+ });
});
}
});
}
+
+
+exports.onDisconnect = function(socket) {
+ var logger = app.set('logger');
+ var chatroomId = socket.handshake.query.id;
+
+ logger.info('##socket.io: disconnect');
+
+ redisClient.hdel("chatroomClients", socket.id);
+};
View
@@ -7,10 +7,10 @@
var connected = false;
if (isUrlOpen) {
- url = host+'/chatrooms/'+chatroomId+'/open?id='+chatroomId+'&urlopen='+isUrlOpen;
+ url = host+'?id='+chatroomId+'&urlopen='+isUrlOpen;
}
else {
- url = host+'/chatrooms/'+chatroomId+'?id='+chatroomId;
+ url = host+'?id='+chatroomId;
}
syaberi.socket = io.connect(url, {
@@ -320,10 +320,10 @@
var connected = false;
if (isUrlOpen) {
- url = host+'/chatrooms/'+chatroomId+'/open?id='+chatroomId+'&urlopen='+isUrlOpen;
+ url = host+'?id='+chatroomId+'&urlopen='+isUrlOpen;
}
else {
- url = host+'/chatrooms/'+chatroomId+'?id='+chatroomId;
+ url = host+'?id='+chatroomId;
}
syaberi.socket = io.connect(url, {
Oops, something went wrong.

0 comments on commit b5682db

Please sign in to comment.