AWS代付、代实名
阿里云国际 | 腾讯云国际

云原生游戏网关架构:EKS + APISIX + Graviton 构建高性能游戏服务网关

亚马逊AWS官方博客

云原生游戏网关架构:EKS + APISIX + Graviton 构建高性能游戏服务网关

前言

在现代游戏运营环境中,随着游戏服务器规模的不断扩大,传统的服务器代理方案面临着诸多挑战。本文将介绍如何使用 API Six 这一高性能网关来解决大规模游戏服务器代理的问题,特别是针对需要使用多个 Network Load Balancer (NLB) 的场景,提供一个更加优雅和高效的解决方案。

在游戏服务架构中,我们经常遇到以下几个关键挑战:

  • 服务器规模问题
  • 随着游戏的成功运营,服务器数量可能从最初的几台扩展到成百上千台
  • 传统的使用多个 NLB 进行代理的方案在管理和维护上变得越来越复杂
  • 成本问题:每增加一个 NLB 都会带来额外的费用支出
  • 安全性考虑
  • 游戏服务器需要防护各种网络攻击
  • 传统的 TCP 协议缺乏足够的安全保护机制
  • 需要在不影响性能的前提下提供安全保障
  • 运维复杂性
  • 多个 NLB 的配置管理较为繁琐
  • 服务器扩缩容时需要频繁调整负载均衡配置
  • 监控和故障排查的难度随着规模增加而增加

面对这些挑战,我们需要一个更现代化的解决方案。API Six 作为一个高性能、可扩展的网关,结合 TLS 加密,能够很好地解决这些问题。在接下来的内容中,我们将详细介绍如何使用 API Six 构建一个高效、安全、易于管理的游戏服务网关系统。

架构介绍

1. 架构整体说明

APIsix核心组件运行于 Amazon EKS(Elastic Kubernetes Service)集群内部。整个系统主要分为两大访问入口:运维(Ops)和玩家(Players),分别通过独立的 ELB(Elastic Load Balancer)接入.(在此建议咱们在部署环境前可以先手动创建ELB, 在EKS中通过TargetGroupBinding的方式来进行绑定服务,这样可以保证后续服务变更时前端接入ELB为同一个.)

2. 流量入口

  • Ops(运维)入口

运维人员通过 ELB 访问 EKS 集群中的 Admin API,实现对平台的管理和监控。

  • Players(玩家)入口

玩家流量同样通过独立的 ELB 进入 EKS 集群,主要访问 API Gateway,进而路由到具体的游戏服务(Game Server)或平台服务(Platform Service)。

3. EKS 集群内部结构

  • Admin API 层

提供管理接口,供运维人员操作和管理整个系统。

  • etcd 层

作为分布式键值存储,负责服务发现、配置管理等核心功能。Admin API 会将变更写入 etcd,API Gateway 通过 watch 机制实时感知服务变化。

  • API Gateway 层

这一层是玩家访问的主要入口,API Gateway 负责根据 etcd 的服务发现信息,将玩家请求路由到后端的具体服务(如 Platform Service 或 Game Server)。

  • 业务服务层

包含平台服务(Platform Service)和多个游戏服(Game Server1、Game Server2 等),这些服务是最终处理玩家请求的核心业务组件。

方案部署

下面我们将逐步来验证整个方案, 方案中我们将采用模拟TCP协议的游戏服务,通过ELB来实现不同游戏服的路由功能.首先我们需要创建一个实验EKS集群, 参考 EKS文档 创建EKS.

创建好EKS后, 添加用户权限

然后创建Access Entry

使用Helm来安装部署APISix

本文采用的部署目标服务器为亚马逊云科技Graviton机型,可以帮助我们发挥APISix的最大性能. 参考步骤如下:

  • 添加相关helm库

helm repo add apisix https://charts.apiseven.com

helm repo update

  • 整理apisix-values.yaml

service:

type: LoadBalancer

annotations:

service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing

service.beta.kubernetes.io/aws-load-balancer-type: nlb

service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip

service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp

Stream proxy configuration (L4 proxy TCP/UDP)

stream:

enabled: true

only: true # Disable HTTP proxy and only enable stream proxy

tcp:

  • addr: 8888

tls: true

udp: []

Enable APISIX Ingress Controller

ingress-controller:

enabled: false

Enable APISIX Dashboard

dashboard:

enabled: true

config:

conf:

etcd:

endpoints:

  • apisix-etcd:2379

prefix: “/apisix”

authentication:

secret: Admin@2025

expire_time: 3600

users:

  • username: admin # dashboard 用户名

password: Admin@2025 # dashboard 密码

ingress:

enabled: true

className: “alb”

annotations:

alb.ingress.kubernetes.io/scheme: internet-facing

alb.ingress.kubernetes.io/target-type: ip

alb.ingress.kubernetes.io/listen-ports: ‘[{“HTTP”: 80}]’

alb.ingress.kubernetes.io/healthcheck-path: “/dashboard”

alb.ingress.kubernetes.io/healthcheck-protocol: HTTP

alb.ingress.kubernetes.io/healthcheck-port: traffic-port

alb.ingress.kubernetes.io/healthcheck-interval-seconds: ’10’

alb.ingress.kubernetes.io/healthcheck-timeout-seconds: ‘5’

alb.ingress.kubernetes.io/success-codes: ‘200’

alb.ingress.kubernetes.io/healthy-threshold-count: ‘2’

alb.ingress.kubernetes.io/unhealthy-threshold-count: ‘2’

hosts:

  • host: “”

paths:

  • “/*”
  • Basic APISIX configuration

apisix:

image:

repository: apache/apisix

tag: 3.7.0-debian

pullPolicy: IfNotPresent

replicaCount: 2

admin:

enabled: true

service:

type: ClusterIP

etcd configuration

etcd:

image:

repository: bitnami/etcd

tag: 3.5.9

pullPolicy: IfNotPresent

persistence:

storageClass: efs-sc

replicaCount: 3

service:

port: 2379

prefix: “/apisix”

timeout: 30

Resource settings

resources:

limits:

cpu: 1000m

memory: 2Gi

requests:

cpu: 500m

memory: 1Gi

Timezone setting

timezone: “UTC”

AWS EKS specific settings

nodeSelector:

kubernetes.io/os: linux

kubernetes.io/arch: arm64

Tolerations for Graviton nodes (if needed)

tolerations:

  • key: “kubernetes.io/arch”

operator: “Equal”

value: “arm64”

effect: “NoSchedule”

Affinity to prefer Graviton nodes

affinity:

nodeAffinity:

preferredDuringSchedulingIgnoredDuringExecution:

  • weight: 100

preference:

matchExpressions:

  • key: kubernetes.io/arch

operator: In

values:

  • arm64
  • 执行命令更新服务

helm install apisix apisix/apisix –create-namespace –namespace ingress-apisix \

–values apisix-values.yaml

  • 如果此处部署有问题,一定要关注一下当前的storageclass是否存在.

etcd:

persistence:

storageClass: efs-sc # 请格外注意此处,否则可能方案部署失败.

另推荐一个小技巧,如果部署出现问题,可以使用Amazon Q CLI来做诊断,整个过程完全自动化,下面是我的步骤截图.

部署 游戏服务

模拟游戏服代码

!/usr/bin/env python3

import socket

import sys

import threading

Get server name from command line argument

server_name = sys.argv[1] if len(sys.argv) > 1 else “Unknown Server”

def handle_client(client_socket, addr):

print(f”[{server_name}] Connection from {addr}”)

try:

Keep connection alive and echo back data

while True:

data = client_socket.recv(1024)

if not data:

break

print(f”[{server_name}] Received: {data}”)

Echo back the data with server name prefix

response = f”[{server_name}] {data.decode(‘utf-8′, errors=’ignore’)}”.encode()

client_socket.send(response)

except Exception as e:

print(f”[{server_name}] Error handling client: {e}”)

finally:

print(f”[{server_name}] Connection closed: {addr}”)

client_socket.close()

def start_server(port=9000):

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

Bind to all interfaces

server.bind((‘0.0.0.0’, port))

server.listen(5)

print(f”[*] {server_name} listening on 0.0.0.0:{port}”)

try:

while True:

client, addr = server.accept()

client_handler = threading.Thread(target=handle_client, args=(client, addr))

client_handler.daemon = True

client_handler.start()

except KeyboardInterrupt:

print(f”[{server_name}] Shutting down server”)

server.close()

if __name__ == “__main__”:

start_server(9000)

模拟EKS中的服务部署代码: test-server-1.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

name: test-server-1

namespace: game

labels:

app: test-server-1

spec:

replicas: 1

selector:

matchLabels:

app: test-server-1

template:

metadata:

labels:

app: test-server-1

spec:

containers:

  • name: tcp-server

image: python:3.9-slim

command: [“python”]

args: [“-u”, “/app/tcp-echo-server.py”, “test-server-1”]

ports:

  • containerPort: 9000

volumeMounts:

  • name: script-volume

mountPath: /app

volumes:

  • name: script-volume

configMap:

name: tcp-echo-server

defaultMode: 0777

apiVersion: v1

kind: Service

metadata:

name: gs-1

namespace: game

labels:

app: test-server-1

spec:

selector:

app: test-server-1

ports:

  • port: 9000

targetPort: 9000

protocol: TCP

type: ClusterIP

test-server-2.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

name: test-server-2

namespace: game

labels:

app: test-server-2

spec:

replicas: 1

selector:

matchLabels:

app: test-server-2

template:

metadata:

labels:

app: test-server-2

spec:

containers:

  • name: tcp-server

image: python:3.9-slim

command: [“python”]

args: [“-u”, “/app/tcp-echo-server.py”, “test-server-2”]

ports:

  • containerPort: 9000

volumeMounts:

  • name: script-volume

mountPath: /app

volumes:

  • name: script-volume

configMap:

name: tcp-echo-server

defaultMode: 0777

apiVersion: v1

kind: Service

metadata:

name: gs-2

namespace: game

labels:

app: test-server-2

spec:

selector:

app: test-server-2

ports:

  • port: 9000

targetPort: 9000

protocol: TCP

type: ClusterIP

部署服务

kubectl create namespace game

kubectl create configmap tcp-echo-server –from-file=tcp-echo-server.py –namespace game

kubectl apply -f test-server-1.yaml

kubectl apply -f test-server-2.yaml

配置证书

当使用TLS的SNI功能时,每个你想要使用SNI的域名或主机名都需要一个有效的证书。这是因为SNI允许从同一个IP地址和端口提供多个主机名服务,而证书用于验证服务器的身份并与客户端建立加密连接。使用OpenSSL为2个Game Server服务生成证书文件和密钥文件。

  • 生成证书

openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout gs-1.key -out gs-1.crt -subj “/CN=gs-1.com” openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout gs-2.key -out gs-2.crt -subj “/CN=gs-2.com”

  • 上传证书到apisix

kubectl port-forward -n ingress-apisix svc/apisix-admin 9180:9180 & sleep 3 curl -X POST http://127.0.0.1:9180/apisix/admin/ssls -H ‘X-API-KEY: edd1c9f034335f136f87ad84b625c8f1’ -d ‘ { “cert”: “‘”$(cat gs-1.crt)”‘”, “key”: “‘”$(cat gs-1.key)”‘”, “snis”: [“gs-1.com”] }’ # Create SSL certificate for gs-2.com curl -X POST http://127.0.0.1:9180/apisix/admin/ssls -H ‘X-API-KEY: edd1c9f034335f136f87ad84b625c8f1’ -d ‘ { “cert”: “‘”$(cat gs-2.crt)”‘”, “key”: “‘”$(cat gs-2.key)”‘”, “snis”: [“gs-2.com”] }’ kill %1

  • 验证证书上传

curl -X GET http://127.0.0.1:9180/apisix/admin/ssls -H ‘X-API-KEY: edd1c9f034335f136f87ad84b625c8f1’

配置路由

下面我们基于已经配置好的证书来配置相关的路由信息, 也就是通常我们在平台服配置好证书后,可以调用相关API来配置路由,命令信息如下:

kubectl port-forward -n ingress-apisix svc/apisix-admin 9180:9180 &

sleep 3

curl -i -X POST http://127.0.0.1:9180/apisix/admin/stream_routes -H ‘X-API-KEY: edd1c9f034335f136f87ad84b625c8f1’ -d ‘{

“upstream”: {

“nodes”: {

“gs-1.game.svc.cluster.local:9000”: 1

},

“type”: “roundrobin”

},

“sni”: “gs-1.com”

}’

curl -i -X POST http://127.0.0.1:9180/apisix/admin/stream_routes -H ‘X-API-KEY: edd1c9f034335f136f87ad84b625c8f1’ -d ‘{

“upstream”: {

“nodes”: {

“gs-2.game.svc.cluster.local:9000”: 1

},

“type”: “roundrobin”

},

“sni”: “gs-2.com”

}’

测试基于SNI的访问

首先获取对应APIsix服务的ALB地址

> kubectl get svc -n ingress-apisix apisix-gateway

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

apisix-gateway LoadBalancer 10.100.xxxx.12 k8s-ingressa-apisixga-xxxxxxx-xxx.elb.us-east-1.amazonaws.com 80:30496/TCP,8888:30694/TCP 3d2h

通过上面返回获取的ALB的地址

openssl s_client -connect k8s-ingressa-apisixga-xxxxx.xxxx.elb.ap-northeast-1.amazonaws.com:8888 \

-servername gs-1.com -quiet

openssl s_client -connect k8s-ingressa-apisixga-xxxx.xxxx.elb.ap-northeast-1.amazonaws.com:8888 \

-servername gs-2.com -quiet

至此可以看到通过不同的SNI我就可以访问到不同的游戏服了,也就解决了使用同一个NLB+APIsix的访问不同的游戏服了.

APISix dashboard访问 (Optional)

我们也可以通过Dashboard来访问当前的APIsix系统,查看相关的配置数据. 不过这里需要我们确认一下ALB的certificate ARN 是不是正确.

kubectl get ingress -n ingress-apisix

APISix 部署亚马逊云科技最佳实践

在生产环境中部署 Apache APISIX 时的关键最佳实践,帮助提升稳定性、性能与可维护性。

核心架构与组件分离

为了保证系统可扩展与高可用,推荐将 APISIX 各核心组件解耦部署:

  • 控制平面(etcd):使用单独部署的 etcd 集群存储路由与插件配置,建议在部署APISix的时候直接指向预先部署好的etcd,至少部署 3 节点,开启数据持久化与快照备份,防止单点故障。
  • 数据平面(APISIX 节点):外部请求由多个 APISIX 实例处理,按需水平扩容。每个实例仅负责流量转发与插件执行,配置从 etcd 动态拉取。
  • 运维监控(Prometheus & Grafana):部署专用的监控系统,采集 APISIX 及 etcd 的指标与日志,实时告警与可视化。
  • 部署模式与扩展策略

  • 无状态部署

APISIX 实例本身应保持无状态,所有动态配置均存储在 etcd。容器化或虚拟机化均可,借助 Kubernetes 等平台实现自动伸缩与滚动升级。

  • 水平扩展

根据 QPS 与响应延迟指标,动态扩缩容。建议在 Kubernetes 中配置 HPA(Horizontal Pod Autoscaler),结合自定义指标(如 CPU、内存或请求速率)自动调整实例数。

  • 灰度发布与回滚

配合 Kubernetes Deployment 或其它发布工具,利用 canary 发布策略逐步下发新版本。在出现问题时,可快速回滚至稳定版本,且不中断大部分流量。

  • 优雅退出, 需要保证apisix pod退出时请求都已经处理完毕

lifecycle:

preStop:

exec:

command: [“sh”, “-c”, “sleep 15 && apisix quit”]

网络与安全

  • 高性能网络

采用 L4 负载均衡(如 Nginx Stream、LVS)将流量分发至 APISIX,避免在 L7 层引入过多额外延迟。

  • TLS 终端

如需 HTTPS 支持,推荐在边缘层(L4)终端 TLS,再以 HTTP 通信至 APISIX;或直接在 APISIX 上使用 ssl 插件终端 TLS,并结合 Cert-Manager 自动续签证书。

  • 访问控制与认证

启用 IP 黑白名单、ACL 插件,并根据业务需求接入 JWT、OAuth2 等认证插件,确保后端服务安全。

配置管理与版本控制

  • 基础配置与热更新

把路由、上游服务、插件配置以 YAML/JSON 格式存储于代码仓库,结合 CI/CD 流水线自动同步至 etcd,实现配置即代码(Configuration as Code)。

  • 版本管理

每次配置变更都需打 tag 并在流水线中校验(lint、单元测试、灰度发布),确保变更可追溯、可回滚。

  • 选择稳定版本,并及时跟进社区的更新.
  • 升级版本时需要进行完整的回归测试,保证新版本的兼容性问题.
  • 性能优化与插件治理

  • 实例选择

优先选择Graviton类型主机,经过多轮测试发现Graviton的机型相对于x86机型可以提供至少2两倍的性能提升,具体请参考社区 Benchmark 链接:.

  • 插件开关粒度

仅在需要的路由上启用插件,避免全局加载过多插件导致请求路径冗余执行。

  • 缓存与限流

利用 proxy-cache 插件对静态或可缓存响应进行本地缓存,减轻后端压力;结合 limit-req、limit-count 插件防止流量突发与恶意攻击。

  • 日志与追踪

启用 skywalking、zipkin 或 opentelemetry 插件,将请求链路与指标上报至分布式追踪系统,快速定位性能瓶颈。

监控告警与健康检查

  • 健康探针

在 Kubernetes 中配置 LivenessProbe 与 ReadinessProbe,APISIX 节点异常时可自动剔除。

  • 关键指标

重点监控请求速率、响应延迟、错误率,以及 etcd 的延迟与 leader 选举状态。根据阈值配置告警规则,保证故障可被及时发现与响应

  • 在实际生产中,如果service数量比较多以及并发大的情况下,需要对netfilter.nf_conntrack_max进行调整。建议结合prometheus和grafana进行告警,及时发现问题并优化相关参数。我们也可以通过采用类似C7gn的机型来提升网络吞吐。
  • 灾备与高可用设计

  • 跨可用区部署

将 etcd 和 APISIX 实例分布在多个可用区或机房,保证单区故障时仍有服务可用。

  • 定期备份

对 etcd 数据进行周期性全量与增量备份,并在异地存储;同时验证备份可用性与恢复流程。

通过上述最佳实践,可以构建一套 高可用、可扩展、易运维 的 APISIX 服务部署体系,满足业务在复杂流量下的稳定运行与快速迭代需求。

总结

借助以上方案通过将所有玩家和运维流量先汇聚到单个NLB,再由部署在 EKS 集群内的 Apache APISIX 按 TLS SNI 把请求精准分发到各游戏服,从而用最少的负载均衡实例实现统一路由、动态服务发现和全链路加密,不仅显著降低 NLB 成本和配置复杂度,还能在服务器扩缩容时保持流量无感知切换,成为高并发游戏场景下经济、高效且易维护的网关架构,同时,借助Graviton,APISix能够实现极高的性价比。

参考内容

https://api7.ai/blog/api7-latency

https://apisix.apache.org/blog/2022/08/12/arm-performance-google-aws-azure-with-apisix/


点击联系客服Telegram
赞(0)
未经允许不得转载:AWS USDT代付 | Payment 解决方案 » 云原生游戏网关架构:EKS + APISIX + Graviton 构建高性能游戏服务网关

AWS代付、代充值免实名

联系我们阿里云国际免实名