GameServer状态
GameServer是Pod的进一步抽象,在创建gs的同时controller会创建对应的Pod,并把Pod的owner设置为该gs。我们通过一个实验来看一下创建gs时gs以及pod的状态变化:
首先开始watch gs和pod对象
kubectl get gs -w
...
kubectl get po -w
...
创建gameserver后,gs和pod的变化如下:
# gameserver
simple-server PortAllocation 0s
simple-server Creating 0s
simple-server Starting 0s
simple-server Scheduled xxx.xxx.xxx.xxx 7036 cn-xxx.xxx.xxx.xxx 0s
simple-server RequestReady xxx.xxx.xxx.xxx 7036 cn-xxx.xxx.xxx.xxx 5s
simple-server Ready xxx.xxx.xxx.xxx 7036 cn-xxx.xxx.xxx.xxx 5s
# pod
simple-server 0/2 Pending 0 0s
simple-server 0/2 Pending 0 0s
simple-server 0/2 ContainerCreating 0 0s
simple-server 2/2 Running 0 3s
simple-server 2/2 Running 0 5s
gs的状态变化:PortAllocation→Creating→Starting→Scheduled→RequestReady→Ready
pod的状态变化:Pending→ContainerCreating→Running
此时,我们尝试删除gs,观察pod与gs的变化:
# gs
simple-server Ready xxx.xxx.xxx.xxx 7036 cn-xxx.xxx.xxx.xxx 6m17s
simple-server Ready xxx.xxx.xxx.xxx 7036 cn-xxx.xxx.xxx.xxx 6m48s
# pod
simple-server 2/2 Terminating 0 6m17s
simple-server 0/2 Terminating 0 6m48s
simple-server 0/2 Terminating 0 6m48s
simple-server 0/2 Terminating 0 6m48s
gs的状态变化:Ready→对象删除
pod的状态变化:Terminating→对象删除
再次创建一个gs,ready后我们删除pod,观察相应变化:
# pod
simple-server 2/2 Terminating 0 21s
simple-server 0/2 Terminating 0 52s
simple-server 0/2 Terminating 0 52s
simple-server 0/2 Terminating 0 52s
# gs
simple-server Unhealthy xxx.xxx.xxx.xxx 7593 cn-xxx.xxx.xxx.xxx 53s
pod的状态变化:Terminating→对象删除
gs的状态变化:Unhealthy
我们结合下面的游戏服状态图和刚刚进行的实验,来说明下各个状态代表的意义
在创建gs后,
- 控制器根据port分配策略默认情况下将gs状态置为
PortAllocation
; - 若端口分配完成,gs进入
Creating
状态,控制器开始创建对应gs的pod; - 待pod对象生成后gs进入
Starting
状态,等待pod调度; - pod调度完成,gs控制器获取pod所在主机IP作为gs的Address,gs进入
Scheduled
状态; - 游戏服进程启动后,通过sdk执行ready(),表示游戏服已经准备完成,gs进入
RequestReady
状态; - 控制器发现对应pod为Running,正常运行,随即将gs置为
Ready
在删除gs时,
- gs等待对应pod删除,pod进入Terminating状态
- 待pod删除完毕,gs对象随即删除
在pod删除时,由于游戏服通过sdk health()发现连接时间超出阈值,则将gs进入Unhealthy
状态
除了刚刚实验观察的现象,我们之前在【Agones系列】Game Server的扩缩容文章中利用GameServerAllocation将gs置为Allocated
状态,代表已分配,等待对应玩家连接;游戏服可主动通过sdk shutdown() 使gs进入Shutdown
状态,进而被删除
Agones SDK
通过对GameServer状态的介绍,我们可以从中看到Agones很大程度上是依赖SDK进行gs的状态管理——游戏服进程需要通过SDK发送grpc/htpp请求上报自身的状态,SDK server作为Pod的sidecar收到请求后调整K8s层面上GameServer的状态。
我们来看下用于生命周期管理的SDK方法有哪些
- Ready()
调用该方法通知Agones游戏已经准备就绪,可以在初始化时调用,或者当游戏结束尝试重复利用gs时调用
- Health()
发送一个ping来确认gs是否健康
- Reserve(seconds)
这个方法设计的初衷是希望保留gs,参数代表保留时间,单位为秒,0代表永久。这类gs不会被GameServerAllocation分配,也不会触发FleetAutoscaler伸缩,游戏本身对自身状态有了更多的维护权利
- Allocate()
通过此方法标记游戏服已被分配。对于匹配类型的游戏来说,已分配将作为gs匹配机制的重要参数,对匹配机制影响较大
- Shutdown()
调用该方法通知Agones关闭当前运行的游戏服
除了主动上报信息,Agones sdk也提供了检索查询的能力
- GameServer()
返回 GameServer 配置和状态
- WatchGameServer(function(gameserver){…})
通过该sdk实现回调方法来处理监听到gs状态变化后的逻辑
对于gs元数据的管理
- SetLabel(key, value)
通过sdk设置gs的label
- SetAnnotation(key, value)
通过sdk设置gs的annotation
对于玩家的追踪
- PlayerConnect(playerID)
通过此方法将玩家的ID上报到Agones,GameServer.Status.Players.Count和 GameServer.Status.Players.IDs将随之更改,Count加一,IDs新增一个条目
- PlayerDisconnect(playerID)
相对应于PlayerConnect,Agones控制器会执行玩家断开连接后的动作,更改对应的GameServer.Status.Players.Count和 GameServer.Status.Players.IDs
- SetPlayerCapacity(count)
更新GameServer.Status.Players.Capacity字段值
- GetPlayerCapacity()
获取GameServer.Status.Players.Capacity字段值
- GetPlayerCount()
获取GameServer.Status.Players.Count字段值
- IsPlayerConnected(playerID)
判断此playerID是否连接
- GetConnectedPlayers()
获取已连接该gs的所有玩家ID