前言
在現代遊戲運營環境中,隨着遊戲服務器規模的不斷擴大,傳統的服務器代理方案面臨着諸多挑戰。本文將介紹如何使用 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庫
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"
}'
測試基於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 發佈策略逐步下發新版本。在出現問題時,可快速回滾至穩定版本,且不中斷大部分流量。
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-goo...
本篇作者
本期最新實驗為《創新基石 —— 基於 Graviton 構建差異化生成式AI向量數據庫》
✨ 在本次實驗中,你可以在基於 Graviton 的 EC2 實例上輕鬆啓動 Milvus 向量數據庫,加速您的生成式 AI 應用。基於 Graviton 的 EC2 實例為您提供極佳性價比的向量數據庫部署選項。
📱 即刻在雲上探索實驗室,開啓構建開發者探索之旅吧!
⏩[點擊進入實驗] 構建無限, 探索啓程!