Higress × OpenKruiseGame 游戏网关最佳实践_博客-Higress官网

Higress × OpenKruiseGame 游戏网关最佳实践

发布时间 2024-01-26


作者:赵伟基,力铭,澄潭

OpenKruiseGame(下文简称:OKG)是一个面向多云的开源游戏服Kubernetes工作负载,是CNCF工作负载开源项目OpenKruise在游戏领域的子项目,其提供了热更新、原地升级、定向管理等常用的游戏服管理功能。而游戏作为典型的流量密集型场景,在吞吐量、延迟性能、弹性与安全性等方面对入口网关提出了很高的要求。
Higress是基于阿里内部两年多的 Envoy 网关实践沉淀,以开源Istio与Envoy为核心构建的下一代云原生网关。Higress实现了安全防护网关、流量网关、微服务网关三层网关合一,可以显著降低网关的部署和运维成本。Higress可以作为K8s集群的Ingress入口网关, 并且兼容了大量K8s Nginx Ingress的注解,可以从K8s Nginx Ingress快速平滑迁移到Higress。同时也支持K8s Gateway API标准,支持用户从Ingress API平滑迁移到Gateway API。
本文将演示Higress如何无缝对接OKG游戏服,并为其带来的优秀特性。

Higress 无缝接入 OKG

前置步骤:

  1. 安装OpenKruiseGame
  2. 安装Higress

OKG提供诸多游戏服热更新和游戏服伸缩的优秀特性,便于游戏运维人员管理游戏服的全生命周期。游戏不同于无状态类型的服务,玩家战斗的网络流量是不允许被负载均衡的,因此每一个游戏服需要独立的访问地址。使用原生工作负载(如Deployment或StatefulSet)时,运维工程师需要为众多游戏服一一配置接入层网络,这无疑阻碍了开服效率,同时手动配置也无形中增加了故障的概率。OKG提供的GameServerSet工作负载可以自动化地管理游戏服的接入网络,大幅度降低运维工程师的负担。对于TCP/UDP网络游戏,OKG提供了诸如HostPort、SLB、NATGW等网络模型;而对于H5/WebSocket类型的网络游戏,OKG也相应提供了Ingress网络模型,如Higress、Nginx、ALB等。image.png
本文采用了一款开源游戏Posio来构建demo游戏服。下述配置中,IngressClassName="higress"指定了Higress作为游戏服的网络层,Higress通过下面配置可以无缝接入Posio游戏服,并且可以基于Annotation实现Higress定义的高阶流量治理等功能。示例Yaml如下所示,GameServerSet生成的游戏服对应的访问域名与游戏服ID相关。在此例中,游戏服0的访问域名为game0.postio.example.com,游戏服1的访问域名为game1.postio.example.com.客户端以此来访问不同的游戏服。

piVersion: game.kruise.io/v1alpha1
kind: GameServerSet
metadata:
name: postio
namespace: default
spec:
replicas: 1
updateStrategy:
rollingUpdate:
podUpdatePolicy: InPlaceIfPossible
network:
networkType: Kubernetes-Ingress
networkConf:
- name: IngressClassName
value: "higress"
- name: Port
value: "5000"
- name: Path
value: /
- name: PathType
value: Prefix
- name: Host
value: game<id>.postio.example.com
gameServerTemplate:
spec:
containers:
- image: registry.cn-beijing.aliyuncs.com/chrisliu95/posio:8-24
name: postio

OKG水平伸缩提供自动扩容、根据游戏服的OpsState缩容、根据DeletionPriority缩容、根据游戏服序号缩容等功能来支持游戏运维的业务需求。水平伸缩的特性在给游戏开发者带来便利的同时,也对入口网关提出了更高的要求:入口网关必须具备配置热更新的能力,完成路由配置的平滑下发。
原因在于:在进行游戏服的扩容时,OKG会同步创建Ingress等相关网络相关资源,以此来保障游戏服的自动上线。如果入口网关不具备配置热更新的能力,在扩容时就,线上玩家就会遇到连接断开等问题,影响游玩体验。

Nginx reload 无法优雅热更新

在游戏服出现扩容,或者定义的路由策略发生变更时,Nginx的配置变更会触发reload,导致上下游的连接都断开并触发重连。
我们以Posio游戏服为例,模拟Nginx+OKG在游戏服扩容时出现的问题。Posio服务端依赖于Socket连接与客户端通信。游戏服扩容时,触发对应的Ingress资源创建,此时Nginx-ingress-controller监听到Ingress资源变更,触发自身reload机制,此时原来与游戏服建立的连接(如本例中的Socket连接会被断开)。在正在游戏的玩家侧的体感便是出现了异常卡顿。
为了直观的展示Nginx Ingress reload带来的影响,我们对Nginx默认配置参数进行一些更改:

Terminal window
kubectl edit configmap nginx-configuration -n kube-system
data:
...
worker-shutdown-timeout: 30s # 一个很难做权衡的配置

Nginx配置参数中worker-shutdown-timeout是Nginx的worker进程优雅下线的超时配置,worker进程会先停止接收新的连接,并等待老的连接逐渐关闭,达到超时时间后,才会去强制关闭当前的所有连接,完成进程退出。
此参数配置过小,会导致大量活跃连接瞬间断开;而此参数配置过大时,又会导致websocket长连接始终维持住Nginx进程,当发生频繁reload时会产生大量shutting down状态的worker进程,老worker占有的内存迟迟得不到释放,可能会导致OOM引发线上故障:
image.png
实际游玩的测试过程如下:客户端访问游戏服,进行正常游玩。在此过程中通过OKG能力触发游戏服扩容,查看此时客户端的响应。通过网页开发者工具可以看到,出现了两条Socket连接,一条是原先浏览器访问游戏服建立,另一条是由于Nginx断连后重连产生的Socket连接。
image.png
原有连接收到的最后一个包时间戳是15:10:26
image.png
而新建连接到获取第一个正常游戏包的时间是15:10:37, 网页与游戏服的断连大概持续5s左右。
image.png
除了玩家的游玩体验受影响,这个机制也会给业务整体稳定性埋雷。在高并发场景下,因为连接瞬断,导致大批量客户端的并发重连,会导致Nginx的CPU瞬间飙升;而后端游戏服务器需要处理更多业务逻辑,一般比网关的资源需求更高,因此Nginx透传过来的大量并发重连,也更容易打垮后端,造成业务雪崩。

Higress 如何实现优雅热更新

Higress支持采用K8s Ingress暴露游戏服外部IP端口,供玩家连接访问。当游戏服伸缩或者定义的路由配置发生变化时,Higress支持路由配置的热更新,以此保障玩家连接的稳定性。
image.png
Higress基于Envoy的精确配置变更管理,做到了真正的配置动态热更新。在 Envoy中downstream对应listener配置,交由LDS实现配置发现;upstream对应cluster配置,交由CDS实现配置发现。 listener配置更新重建,只会导致downstream连接断开,不会影响upstream的连接; downstream和upstream的配置可以独立变更,互不影响。再进一步,listener下的证书(cert),过滤器插件(filter),路由(router)均可以实现配置独立变更,这样不论是证书/插件/路由配置变更都不再会引起downstream连接断开。
精确的配置变更机制,除了让Envoy可以实现真正的热更新,也让Envoy的架构变的更可靠,Envoy配置管理从设计之初就是为数据面(DP)和控制面(CP)分离而设计的,因此使用gRPC实现远程配置动态拉取,并借助proto来规范配置字段,并保持版本兼容。这个设计实现了数据面和控制面的安全域隔离,增强了架构的安全性。
使用OKG接入Higress后,下面依然模拟客户端访问游戏服,进行正常游玩。在此过程中通过OKG能力触发游戏服扩容,查看此时客户端的响应。通过网页开发者工具可以看到,在此过程中客户端与游戏服建立的连接稳定不受影响。
image.png
此外,在大规模游戏服场景下,每个游戏服对应一个独立的Ingress,会产生大量的Ingress资源,我们测试在达到1k级别规模时,Nginx Ingress要新扩一个游戏服需要分钟级生效,而Higress可以在秒级生效。Nginx Ingress的这一问题也被Sealos踩坑,并最终通过切换到Higress解决,有兴趣可以阅读这篇文章了解:《云原生网关哪家强:Sealos 网关血泪史》

欢迎加入OKG和Higress开源社区交流

okg.pnghigress-dingding.png