大挑战(暂定名)服务器架构
大挑战是一款手机休闲网络游戏,游戏形式为开房间,每个房间内最大能容纳20名玩家游戏.
服务器结构划分
服务器按功能分成3类:
-
redis服务器,负责数据的存储
-
主逻辑服务器,战斗等游戏逻辑的处理
-
网关服务器,负责用户的接入和账号验证
先期考虑一个服务器组能容纳5W人同时在线,需部署3台服务器,基本配置如下:
-
redis服务器, 4核心cpu,64GB内存,3T硬盘,高主频
-
主逻辑服务器, 16核心cpu,64GB内存,1T硬盘,高主频
-
网关服务器,8核心cpu,16GB内存,500GB硬盘,一般即可
服务器逻辑视图
---------------
|redis service|<------
--------------- |
^ |
| |
GameServer V |
-------------------------------------------------------------------- |
|super service| battle service|battle service| .... |asyndb service| |
-------------------------------------------------------------------- |
^ |
| |
--- V---------------------------------------------------------------- |
| | |
------------------ | |
|to super service| GateServer | |
------------------ | |
| | |
--------------------------------------------------------------------| |
|agent service|agent service|agent service| ... |asyndb service|<-----
--------------------------------------------------------------------|
client client client ...
网关用户id的设计
网关用户id用以唯一标识处于agent service中的玩家
--------------------------------------
|3位 agent service号|14用户ID号|15位递增值|
--------------------------------------
如上图所示,用户在网关的唯一ID用一个32位整数标识:
其中3位用于作为agent service号,取值0-7也就是一台物理机器最多可以加载8个agent service.
14位的用户编号,这个编号在agent service中唯一,也就是每个agent service最多容纳8191个玩家(0为非法值)
15位递增值,在agent service内递增,每分配一个用户ID加1,用以防止从inter服务器中过来的消息被转发往一个已过期的用户.
消息广播的处理
当gameserver需要广播消息的时候,将需要接收消息的玩家的网关用户标识填入消息包尾部发往gateserver,由to super service
接收,to super service接收到包后直接推送到所有agent service的消息队列中,由agent serviece自己判断需要发往哪些用户.
Gameserver的消息处理
玩家的请求消息在Gameserver中只能被一个消息分发器处理,消息首先被super service接收到,如果玩家当前不在任何一个battle
service中,则直接由super service处理这个请求,否则请求消息被投递到玩家所在的battle service的消息队列,由相应的
battle service处理请求,这样保证了玩家数据在任何时刻都只能被一个线程修改.
移动处理及同步
服务器采用2D网络作为地图,x,y坐标分别用16位无符号整数表示,则横竖能容纳一个65536X65536的网格,一个玩家站立的位置占4个格子,
2个玩家的位置表示1米,则一个地图大小为16384X16384米.
玩家请求移动时由客户端发送一个目标点坐标,服务器根据地形信息计算路径,如果无法到达用户请求的目标点则到达一个可以到达的点上.服
务器根据玩家的移动速度和路径计算出到达目标点的时间.这个目标点和到达时间合并在一起用一个64位整型表示,作为玩家的一个属性,每当
玩家请求移动时将会导致这个属性变更,同步给视野内的其它客户端,只要客户端和服务器使用同样的寻路算法,即可正确表现玩家的移动请求.
服务器将移动请求的处理分成两部分,第一部分就是上面描述的计算路径和到达时间点,第二部分是根据路径在服务器中移动玩家对象.这一步由
定时器处理,例如以100ms的频率运行,每次定时器到时根据玩家的移动速度和消逝的时间计算出可以移动几个格子,然后从移动路径中删除这
几个格子,并将玩家坐标设置到路径队列的最后一个格上,然后刷新AOI信息.
在移动的过程中,移动属性可能会变化,例如,在玩家进行一个长距离移动的过程中受到攻击,可能减缓其移动速度,又或者玩家可能打断了现有
的移动请求.对于第一种情况,移动的目标点不变,但到达时间被延后,则需要将改变后的移动属性重新同步一次,让客户端表现移动速度的减缓.
对于第二种情况,除了将当前玩家所在点和当前时间作为移动属性同步出去,让客户端表现移动停止之外,还要将移动路径队列清除以防止服务器
在下一次移动定时器到期时继续移动玩家的位置.
项目地址:https://github.com/sniperHW/KendyNet/tree/master/big challenge