关于socket.io的群集解决方案,官网中给出了3个示例代码。除了负载均衡的软件不同,其他的代码其实都是一样的,分别为:nginx
,httpd
, haproxy
。以下以nginx为例说明。官网给的demo基于docker,让你可以直接运行。代码结构如下:
- 首先代码
index.js
中加入redis
适配var io = require('socket.io')(3000); var redis = require('socket.io-redis'); io.adapter(redis({ host: 'localhost', port: 6379 }));
除此之外,和单机下的代码并无区别。由于客户端可能连接到集群中不同的节点,为了在集群中不同的节点之间传递消息,socket.io官方以redis的发布订阅功能为基础做了消息路由分发:socket.io-redis
。socket.io-redis
在节点向客户端群发消息时会将该消息发布到redis的订阅队列中,让其他节点能够订阅到该消息,从而实现节点间消息推送。
nginx
配置
worker_processes 4;
events {
worker_connections 1024;
}
http {
server {
listen 80;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://nodes;
# enable WebSockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
upstream nodes {
# enable sticky session
ip_hash;
server server-john:3000;
server server-paul:3000;
server server-george:3000;
server server-ringo:3000;
}
}
该配置文件,在请求头中加入 Upgrade
来支持 websocket
使用ip_hash
保证同一个ip请求到固定的容器。将请求分发给四个服务:server-john
,server-paul
,server-george
,server-ringo
.
docker-compose
配置
nginx:
build: ./nginx
links:
- server-john
- server-paul
- server-george
- server-ringo
ports:
- "3000:80"
server-john:
build: ./server
links:
- redis
expose:
- "3000"
environment:
- NAME=John
server-paul:
build: ./server
links:
- redis
expose:
- "3000"
environment:
- NAME=Paul
server-george:
build: ./server
links:
- redis
expose:
- "3000"
environment:
- NAME=George
server-ringo:
build: ./server
links:
- redis
expose:
- "3000"
environment:
- NAME=Ringo
redis:
image: redis:alpine
expose:
- "6379"
该配置文件中,nginx依赖四个web服务,每个web服务都依赖redis。每个服务都暴露3000端口。environment
环境变量用于标示当前的服务器名称,以此来告诉客户端请求被分发到哪台服务器了。会在index.js
以下的代码中用到。
var serverName = process.env.NAME || 'Unknown';
- 每个服务的docker配置
FROM mhart/alpine-node:6
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install
# Bundle app source
COPY . /usr/src/app
EXPOSE 3000
CMD [ "npm", "start" ]
该配置功能:拷贝package.json,安装依赖,拷贝源文件,启动服务。
由于示例采用docker安装,只要你的电脑中有安装docker,当我们下载完官方的代码,直接在代码根目录下运行以下命令便可启动服务进行测试。
$ docker-compose up -d
注意
官网的 socket.io-redis
库只有在消息广播(socket.broadcast.emit)
的时候,才能生效。对于私发的消息,如果想在集群不同节点之间传递还是需要自己手动写一个解决方案,具体可以参考redis的发布订阅功能在nodejs下的api。