lang/node

socket.io 1.3.7 cluster On Nodejs 5.1.0

C/H 2015. 12. 10. 08:30

socket.io 1.3.7 + socket.io-redis On Node v5.1.0 에서 Cluster로 2개 이상 cluster.fork()를 할 경우 에러발생.

에러코드

WebSocket connection to 'ws://localhost:8988/socket.io/?EIO=3&transport=websocket&sid=C4JjFse-flmhXOpLAAAB' failed: Connection closed before receiving a handshake response
에러 자체는 연결이 되지 않는 것에 대한 문구지만 DEBUG=* node cluster.js 에서 에러가 표시되지 않음. 그 외 서버에서는 connect는 문제가 없지만 emit 발송에서 engin.io log 후 중지 되는 현상이 발생

cluster 기능 적용

/* cluster.js */
require('magic-globals');
var cluster 	= require('cluster');
var net			= require('net');
var ip			= require('ip');
var num_processes 	= _CONFIG.getENV()=='production'?
			Math.round( require('os').cpus().length * 1.5 ): 	// CPU 자원 최대한 활용
			2; 
cluster.setupMaster({
	exec:'./server.js',
	args: [],
	silent: false
});

if (cluster.isMaster) {
	var logo = require('./logo');
	
	// 저장소
	var workers = [];
	// fork 
	var spawn = function(i) {
		workers[i] = cluster.fork({fork:i});

		// Optional: Restart worker on exit
		workers[i].on('exit', function(worker, code, signal) {
			console.log('respawning worker', i);
			spawn(i);
		});
	};

	// 프로세스 개수만큼 fork
	for (var i = 0; i < num_processes; i++) {
		spawn(i);
	}

	/* IP로 동일한 fork 연결 
	var worker_index = function(ip, len) {
		var s = '';
		for (var i = 0, _len = ip.length; i < _len; i++) {
			if (ip[i] !== '.') {
				s += ip[i];
			}
		}
		
		return Number(s) % len;
	}; /**/

	// 외부에서 접근하는 연결서버를 만든다.
	var server = net.createServer({ pauseOnConnect: true }, function(connection) {

		// 연결된 IP로 fork된 데몬을 동일하게 유지한다.
		//var worker = workers[worker_index(ip.address(), num_processes)];
		var worker = workers[ ip.toLong(ip.address())%num_processes ];
		
		worker.send('sticky-session:connection', connection);
	}).listen( port );
	
}

cluster.on('exit', function(worker, code, signal) {
	console.error( '#####', __line, 'worker ', worker, code, signal );
	cluster.fork( {fork: worker.process.env.fork} );
	console.log( '#####', __line, 'worker', worker.process.env.fork, 'restart' );  
});
/* server.js 에서 cluster.js 와 동기화를 위한 코드 적용  */
// 마스터에서 수신포트를 사용하니 server.js에서는 포트를 사용하지 않는다.
var app = new express();

// 미들웨어, 라우터 적용 

// 외부에 내부 포트를 노출하지 않는다.
var server = app.listen(0, 'localhost'),
        io = sio(server);

// Redis 어댑터 사용
io.adapter(sio_redis({ host: 'localhost', port: 6379 }));

// socket.io 미들웨어 사용 

// 마스터(cluster.js)에서 보낸 메세지를 받는다. 나머지 다른것은 무시한다.
process.on('message', function(message, connection) {
	if (message !== 'sticky-session:connection') {
		return;
	}

	// 마스터에서 보낸 연결 이벤트를 fork된 현재 서비스에 에뮬레이트(연결…이라고 생각)한다.
	server.emit('connection', connection);

	connection.resume();
});

cluster.js, server.js 적용후 SSL 문제

에러는 발생하지 않지만 서버접근이 되지 않는 문제가 발생함. 에러도 없음. ㅡ.ㅡ
var worker = workers[ ip.toLong(ip.address())%num_processes ]; 등으로 컨텍스트 변경없이 코드 리팩토링을 하니 문제 없이 작동함.

반응형

'lang > node' 카테고리의 다른 글

socket.io room join socket.id express api On Nodejs 5.1.0 + socket.io 1.3.7  (0) 2015.12.17
Nginx LoadBalancer + Nodejs socket.io  (0) 2015.12.16
PM2  (0) 2015.12.09
socket.io listen OR attach  (0) 2015.12.08
Socket.io 0.9.x, 1.x Protocol  (0) 2015.12.04