- NodeJS|Socket.IO how to send server handler to workers?
- Sticky session
- node-cluster-socket.io
- 【Node.js】socket.io + cluster で 400 (Bad Request) + Connection closed before receiving a handshake responseAdd Star
- Horizontally Scaling Node.js and WebSockets with Redis
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 |