背景
之前做了一些游戏,技术方案是 Hyperf (Swoole)的单一 worker 模式来做的逻辑处理(为了便于维护,使用的对象而非 Table),这样可以将数据在内存中处理,大幅度提高响应速度,但是会造成 CPU 资源的浪费,故而需要多开几个 Server,关于如何维护服务数据,以后可以单开一篇来说明
为什么要分流
你说呢
分流的策略
这个有很多种选择,由于我的游戏是基于【房间】或者【群组】的,所以我的想法是将用户依据用户所处的群组来分流,群组 A 的用户应当对于群组 B 的事情一无所知
分流的工具
NGINX 的 hash 分流,配置文件如下
upstream game_nodes {
hash $http_gid;
server ip1:port1;
server ip2:port2;
}
server {
listen 80;
server_name domains;
location / {
proxy_set_header Upgrade "websocket";
proxy_set_headerConnection "upgrade"
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_http_versions 1.1;
# 转发到多个 ws server
proxy_pass http://game_nodes;
}
}
围绕这个配置文件来说明一下分流的方案
- 首先在客户端的请求头中增加一个 gid, 也就是用户所处的群组 id
- 服务端开启 N 个服务,也即 ip1:port1, ip2:port2…
- 设置 upstream 并指定分流策略为依据 gid 的值进行 hash 分流以期群组在节点分布均匀(注意,这并不能保证压力均匀)
- upstream.hash 配置项目表示使用一致性 hash 来分发流量
- $http_gid 表示从请求头中获取 gid 字段
- 在 server 配置项中使用反向代理将请求转发到上文设置的 upstream ,也即 game_nodes
分流的问题以及解决方法
因为游戏服务通信量是很大的,所以在某个节点重启中这个节点的负载会被分摊去其他节点,这个过程可能会出现群组不一致的问题
对于这个情况,有一个不成熟的方案,首先关闭 nginx ,使得客户端处于断网重连状态,然后重启所有节点后开启 nginx 响应