前言
在现代游戏运营环境中,随着游戏服务器规模的不断扩大,传统的服务器代理方案面临着诸多挑战。本文将介绍如何使用 API Six 这一高性能网关来解决大规模游戏服务器代理的问题,特别是针对需要使用多个 Network Load Balancer (NLB) 的场景,提供一个更加优雅和高效的解决方案。 在游戏服务架构中,我们经常遇到以下几个关键挑战:
1、 服务器规模问题
- 随着游戏的成功运营,服务器数量可能从最初的几台扩展到成百上千台
- 传统的使用多个 NLB 进行代理的方案在管理和维护上变得越来越复杂
- 成本问题:每增加一个 NLB 都会带来额外的费用支出
2、 安全性考虑
- 游戏服务器需要防护各种网络攻击
- 传统的 TCP 协议缺乏足够的安全保护机制
- 需要在不影响性能的前提下提供安全保障
3、运维复杂性
- 多个 NLB 的配置管理较为繁琐
- 服务器扩缩容时需要频繁调整负载均衡配置
- 监控和故障排查的难度随着规模增加而增加
面对这些挑战,我们需要一个更现代化的解决方案。API Six 作为一个高性能、可扩展的网关,结合 TLS 加密,能够很好地解决这些问题。在接下来的内容中,我们将详细介绍如何使用 API Six 构建一个高效、安全、易于管理的游戏服务网关系统。
📢限时插播:在本次实验中,你可以在基于 Graviton 的 EC2 实例上轻松启动 Milvus 向量数据库,加速您的生成式 AI 应用。
⏩快快点击进入《创新基石 ------ 基于 Graviton 构建差异化生成式AI向量数据库》实验
📱 即刻在云上探索实验室,开启构建开发者探索之旅吧
架构介绍
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的最大性能. 参考步骤如下:
1、添加相关helm库
csharp
helm repo add apisix https://charts.apiseven.com
helm repo update
2、整理apisix-values.yaml
yaml
# 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
3、执行命令更新服务
css
helm install apisix apisix/apisix --create-namespace --namespace ingress-apisix \
--values apisix-values.yaml
4、如果此处部署有问题,一定要关注一下当前的storageclass是否存在.
yaml
etcd:
persistence:
storageClass: efs-sc # 请格外注意此处,否则可能方案部署失败.
另推荐一个小技巧,如果部署出现问题,可以使用Amazon Q CLI来做诊断,整个过程完全自动化,下面是我的步骤截图.
部署 游戏服务
模拟游戏服代码
python
# 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
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
部署服务
vbscript
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服务生成证书文件和密钥文件。
1、生成证书
csharp
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"
2、上传证书到apisix
javascript
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
3、验证证书上传
ruby
curl -X GET http://127.0.0.1:9180/apisix/admin/ssls -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1'
配置路由
下面我们基于已经配置好的证书来配置相关的路由信息, 也就是通常我们在平台服配置好证书后,可以调用相关API来配置路由,命令信息如下:
vbnet
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地址
arduino
> 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的地址
arduino
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 发布策略逐步下发新版本。在出现问题时,可快速回滚至稳定版本,且不中断大部分流量。
bash
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能够实现极高的性价比。
参考内容
api7.ai/blog/api7-l... apisix.apache.org/blog/2022/0...
本篇作者 
本期最新实验为《创新基石 ------ 基于 Graviton 构建差异化生成式AI向量数据库》
✨ 在本次实验中,你可以在基于 Graviton 的 EC2 实例上轻松启动 Milvus 向量数据库,加速您的生成式 AI 应用。基于 Graviton 的 EC2 实例为您提供极佳性价比的向量数据库部署选项。
📱 即刻在云上探索实验室,开启构建开发者探索之旅吧!
⏩[点击进入实验] 构建无限, 探索启程!