node.js socket.io의 cluster 사용 참고사항
기본적으로 클라이언트가 transports: ['websocket'] 기반으로만 사용한다면 문제가 되지 않는다
하지만 XHR Polling 또는 JSONP Polling 사용시에는
{"code":1,"message":"Session ID unknown"}
문제가 발생한다
폴링은 여러번 요청을 보내는데 여러 process중에 같은 process로 붙을 수 없어서 Session ID 찾을수 없는 듯하다
그래서
http://socket.io/docs/using-multiple-nodes/
메뉴얼 사이트에 보면 제시하는 방법이
1. NginX configuration
node.js에서 제공되는 cluster를 사용하지 않고 NginX를 앞단에 둔다
그리고 upstream 을 통해서 프록시 서버를 둔다 그리고 ip_hash 를 설정해서 같은 ip의 경우 같은 포트(즉같은프로세스)를 보도록 해서 문제를 해결한다
※ node.js socket.io는 데몬을 각각 포트별로 여러개 띄워야된다.
2. Using Node.JS Cluster
추가로 node.js Cluster 사용시에는 https://github.com/indutny/sticky-session
(나도 아직 테스트 제대로 해보지 않았음)
3. Passing events between nodes
그리고 클러스터 구성시에 유저들간의 메세지(이벤트) 전달은 https://github.com/automattic/socket.io-redis
socket.io-redis이용해서 가능한 방법을 제공해주고있다
테스트해보니까 다른 node 프로세스로 붙어있지만 아래 명령어 실행시 이상없이 잘 동작한다.
socket.broadcast.emit / 자신제외 전체유저
io.sockets.in(socket_id).emit / 특정유저에게메세지전달
socket.broadcast.to(room_id).emit / 같은 룸에 입장된 유저에게 메세지전달
추가로 용량 처리가 많을 경우 detect_buffers 옵션을 true 해줘야됨
var redis = require("redis"); var redisAdapter = require('socket.io-redis'); var pub = redis.createClient("/tmp/redis.sock",{ detect_buffers: true }); var sub = redis.createClient("/tmp/redis.sock",{ detect_buffers: true }); io.adapter( redisAdapter({pubClient: pub, subClient: sub}) );
※ socket.io 서비스 하기 위해서 유저별 socket.id를 관리하는 redis 와 서비스 비지니스 로직에 적절한 cluster 기능을 잘 구성해서 사용할 듯합니다.
해당 이슈로써 https://github.com/Automattic/socket.io/issues/1503 어느정도 방안에 대한 댓글을 볼수있다.
아래와 같은 것들도 있는 듯하다 아무쪼록 서비스 방향에 결정되면 좀더 연구해봐야될듯함
https://github.com/TopCloud/socketcluster
https://devcenter.heroku.com/articles/node-sessions