WebSocket+Ngnix负载均衡处理

项目实施

继上一次解决SocketIO解决504错误,在项目实施中采用ngnix实现websocket的负载均衡,又采坑了。网络拓扑如下示:

网络拓扑1

ngnix转发飘移问题

发现服务端监听到的client连接频繁的出现重连现象。
sessionId重连

问题分析

socketIO在请求时,以 long-polling的方式进行通信。而ngnix默认的负载均衡方式是轮询(round robin),会根据请求的时间顺序去分配后端服务。就会导致是上面的建立连接(onConnect)和断开连接(onDdisConnect)的问题的出现。
url

问题解决

ngnix负载均衡策略

轮询(默认)

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。

1
2
3
4
upstream backserver {
server 192.168.0.14;
server 192.168.0.15;
}

指定权重

指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。

1
2
3
4
upstream backserver {
server 192.168.0.14 weight=10;
server 192.168.0.15 weight=10;
}

IP绑定 ip_hash

每个请求按访问ip的hash结果分配,这样每个请求访问固定一个后端服务器,假如当前server不能提供服务,就会根据当前的哈希值再哈希出一个新哈希值,选择另一个服务器继续尝试,尝试的最大次是upstream中server的个数,假如server的个数超过20,也就是要最大尝试次数在20次以上,当尝试次数达到20次,仍然找不到一个合适的服务器,ip_hah策略不再尝试ip哈希值来选择server,而在剩余的尝试中,它会转而使用RR的策略,使用轮循的方法,选择新的server。同时,可以解决session的问题

1
2
3
4
5
upstream backserver {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}

fair(第三方)

按后端服务器的响应时间来分配请求,响应时间短的优先分配。

1
2
3
4
5
upstream backserver {
server server1;
server server2;
fair;
}

url_hash(第三方)

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。

1
2
3
4
5
6
upstream backserver {
server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;
}

综上,WebSocket+Ngnix采用ip_hash的负载均衡策略,防止请求漂移问题。

  • 注意均衡算法要使用 ip_hash , 防止使用 long-polling 通信时请求分发到了不同的服务器导致异常。

  • 刷新浏览器时,相当与客户端首先disconnect然后重新建立一次connect。并且此socket.io会默认重连之前断开的连接。

ngnix配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
upstream websocket {
ip_hash;
server 192.168.0.1:9000;
server 192.168.0.2:9000;
}

server {
listen 9000;
charset utf-8;
location / {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
}
}

参考资料

Alan Zhang wechat
欢迎您扫一扫上面的微信公众号“补愚者说”,订阅我的博客!