810
社区成员
发帖
与我相关
我的任务
分享
在现代游戏运营环境中,随着游戏服务器规模的不断扩大,传统的服务器代理方案面临着诸多挑战。本文将介绍如何使用 API Six 这一高性能网关来解决大规模游戏服务器代理的问题,特别是针对需要使用多个 Network Load Balancer (NLB) 的场景,提供一个更加优雅和高效的解决方案。在游戏服务架构中,我们经常遇到以下几个关键挑战:
1、 服务器规模问题
随着游戏的成功运营,服务器数量可能从最初的几台扩展到成百上千台
传统的使用多个 NLB 进行代理的方案在管理和维护上变得越来越复杂
成本问题:每增加一个 NLB 都会带来额外的费用支出
2、 安全性考虑
游戏服务器需要防护各种网络攻击
传统的 TCP 协议缺乏足够的安全保护机制
需要在不影响性能的前提下提供安全保障
3、运维复杂性
多个 NLB 的配置管理较为繁琐
服务器扩缩容时需要频繁调整负载均衡配置
监控和故障排查的难度随着规模增加而增加
面对这些挑战,我们需要一个更现代化的解决方案。API Six 作为一个高性能、可扩展的网关,结合 TLS 加密,能够很好地解决这些问题。在接下来的内容中,我们将详细介绍如何使用 API Six 构建一个高效、安全、易于管理的游戏服务网关系统。
📢限时插播:在本次实验中,你可以在基于 Graviton 的 EC2 实例上轻松启动 Milvus 向量数据库,加速您的生成式 AI 应用。
⏩快快点击进入《创新基石 —— 基于 Graviton 构建差异化生成式AI向量数据库》实验
📱 即刻在云上探索实验室,开启构建开发者探索之旅吧!
APIsix核心组件运行于 Amazon EKS(Elastic Kubernetes Service)集群内部。整个系统主要分为两大访问入口:运维(Ops)和玩家(Players),分别通过独立的 ELB(Elastic Load Balancer)接入.(在此建议咱们在部署环境前可以先手动创建ELB, 在EKS中通过TargetGroupBinding的方式来进行绑定服务,这样可以保证后续服务变更时前端接入ELB为同一个.)
Ops(运维)入口运维人员通过 ELB 访问 EKS 集群中的 Admin API,实现对平台的管理和监控。
Players(玩家)入口玩家流量同样通过独立的 ELB 进入 EKS 集群,主要访问 API Gateway,进而路由到具体的游戏服务(Game Server)或平台服务(Platform Service)。
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.
然后创建Access Entry
本文采用的部署目标服务器为亚马逊云科技Graviton机型,可以帮助我们发挥APISix的最大性能. 参考步骤如下:
1、添加相关helm库
helm repo add apisix https://charts.apiseven.com
helm repo update
2、整理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
3、执行命令更新服务
helm install apisix apisix/apisix --create-namespace --namespace ingress-apisix \
--values apisix-values.yaml
4、如果此处部署有问题,一定要关注一下当前的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服务生成证书文件和密钥文件。
1、生成证书
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
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、验证证书上传
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"
}'
首先获取对应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的访问不同的游戏服了.
我们也可以通过Dashboard来访问当前的APIsix系统,查看相关的配置数据. 不过这里需要我们确认一下ALB的certificate ARN 是不是正确.kubectl get ingress -n ingress-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 发布策略逐步下发新版本。在出现问题时,可快速回滚至稳定版本,且不中断大部分流量。
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-latencyhttps://apisix.apache.org/blog/2022/08/12/arm-performance-google-aws-azure-with-apisix/
本篇作者

本期最新实验为《创新基石 —— 基于 Graviton 构建差异化生成式AI向量数据库》
✨ 在本次实验中,你可以在基于 Graviton 的 EC2 实例上轻松启动 Milvus 向量数据库,加速您的生成式 AI 应用。基于 Graviton 的 EC2 实例为您提供极佳性价比的向量数据库部署选项。
📱 即刻在云上探索实验室,开启构建开发者探索之旅吧!
⏩[点击进入实验] 构建无限, 探索启程!