亚马逊AWS官方博客

使用 Amazon GameLift Servers为游戏构建 DDoS 防护与延迟优化

摘要:多人在线游戏面临两大网络挑战——DDoS 攻击和跨区域延迟。本文介绍 Amazon GameLift Servers 新推出的 Player Gateway(玩家网关)和 Ping Beacons(延迟探测)功能,并通过开源的 C++ Client SDK 和完整的 Sample App,手把手演示如何集成这两项能力,包括使用 AWS CDK 一键部署基础设施、对比中继模式与直连模式的差异


一、背景:多人游戏的网络安全与体验挑战

多人在线游戏的服务器长期面临两个核心网络问题:

1. DDoS 攻击:竞技游戏中,恶意玩家通过获取游戏服务器 IP 发起 DDoS 攻击,导致整局玩家掉线。由于 UDP 协议无连接、无状态、源 IP 可伪造,传统的 TCP 层防护手段(如 SYN Cookie)完全失效。现有方案通常依赖 AWS Shield Advanced + Network Load Balancer 或第三方 DDoS 防护服务,不仅成本高昂,还需要手动维护字节匹配规则(byte matching patterns),且防护本身会引入额外延迟。更关键的是,这些方案是被动响应式的——检测攻击需要数分钟,缓解措施生效又需要数分钟,而一局竞技游戏可能只有 15-30 分钟,等防护生效时玩家早已掉线。

2. 跨区域延迟:全球化运营的游戏需要将玩家放置到延迟最低的区域,但缺乏标准化的延迟测量手段。如果自建 ping 基础设施,开发者需要在全球各区域部署 UDP echo 服务器、配置 DNS 解析、实现统计逻辑(多次测量取平均、处理丢包和异常值)、维护服务器可用性和扩缩容——这些工作与游戏核心玩法无关,却消耗大量工程资源。

Amazon GameLift Servers 针对这两个痛点推出了两项新功能:

  • Player Gateway(玩家网关)—— 在游戏客户端和服务器之间建立中继网络,隐藏服务器真实 IP,在流量到达服务器前进行验证和过滤
  • Ping Beacons(延迟探测)—— 提供全球各区域的 UDP 延迟测量端点,客户端并行测量后将数据用于最优区域放置

为了降低集成门槛,AWS开源了 Amazon GameLift Servers Client SDK for C++,提供开箱即用的端点管理、健康追踪、算法选择等能力。本文将深入介绍这两项功能的技术原理,并通过完整的 Sample App 演示端到端集成流程。

二、核心优势:为什么选择 GameLift Servers DDoS Protection

在深入技术细节之前,先总结 Player Gateway 和 Ping Beacons 的核心卖点:

  • 零额外费用

Player Gateway 和 Ping Beacons 均对 Amazon GameLift Servers 客户免费提供,无需额外付费。相比之下,传统方案中 AWS Shield Advanced 每月固定费用 $3,000 起,第三方游戏 DDoS 防护服务的成本更是因厂商而异。

  • 延迟影响可忽略不计

Player Gateway 的中继网络与游戏服务器共置部署(co-located)在同一基础设施中,因此中继跳转引入的额外延迟可忽略不计(negligible)。对于 FPS、MOBA 等对延迟极度敏感的游戏类型,这一点至关重要——玩家在获得 DDoS 防护的同时,不会感知到任何游戏体验的下降。

  • 主动防护 vs 被动响应

传统 DDoS 防护是被动响应式的:先检测攻击(数分钟),再应用缓解措施(又数分钟),期间玩家可能已经掉线。Player Gateway 采用主动防护模式——所有流量在到达游戏服务器前必须通过令牌验证,未授权流量从一开始就被拦截,无需等待检测和响应。同时,每个玩家有独立的流量限制,即使单个玩家的令牌被盗用,也无法对整个游戏会话造成影响。

  • Ping Beacons:比 ICMP 更准确的延迟测量

多人游戏的实际流量使用 UDP 协议,而传统的 ICMP ping 走的是不同的网络路径,测量结果可能与真实游戏延迟存在偏差。Ping Beacons 使用 UDP 协议测量延迟,反映的是玩家到游戏服务器的真实网络路径延迟。端点覆盖所有 GameLift Servers 支持的 AWS Region 和 Local Zone,客户端并行发送 3 次 UDP ping 取平均值,约 3 秒即可完成全球延迟测量。

  • 服务器端零改动

Player Gateway 的所有集成工作都在客户端和后端完成,游戏服务器代码无需任何修改。只要 Fleet 使用 Server SDK 5.0+,中继网络对服务端完全透明。这意味着已有的游戏服务器可以直接获得 DDoS 防护能力,无需重新开发或部署。

三、Player Gateway:中继网络实现 DDoS 防护

3.1 工作原理

Player Gateway 的核心思想是:客户端永远不直连游戏服务器,而是通过中继端点通信。

当 Fleet 启用 Player Gateway 后,Amazon GameLift Servers 通过 GetPlayerConnectionDetails API 返回:

  • 多个中继端点:IP 地址和端口,负责将流量路由到游戏服务器
  • Player Gateway Token:Base64 编码的令牌,必须解码后拼接到每个 UDP 包的头部
  • 过期时间:令牌的有效期,需要每 60 秒刷新

中继端点在转发前会验证令牌,剥离令牌后将原始游戏数据发送给服务器。服务器端完全无感知——不需要任何代码改动。

3.2 为什么需要 Client SDK

虽然 Player Gateway 的客户端逻辑本质上不复杂(拼接 token、追踪健康、选择端点),但要做好并不容易:

  • 端点健康追踪:需要根据收包情况判断哪些中继端点健康,哪些需要切换
  • 地址规范化:多个中继端点指向同一个服务器,但上层游戏逻辑通常假设只有一个服务器地址。需要将所有中继地址映射为一个 canonical 地址
  • 算法选择:不同游戏阶段(大厅 vs 实时对战)适合不同的端点选择策略
  • 线程安全:发送和接收通常在不同线程,共享数据需要加锁保护
  • 定期刷新:每 60 秒需要后台刷新端点和 token,否则连接会中断

Client SDK 的 PlayerGatewayManager 封装了以上所有逻辑,开发者只需在 UDP 收发路径上插入几行调用即可。

3.3 服务器端零改动

这是 Player Gateway 最大的优势之一:游戏服务器代码完全不需要修改。只要 Fleet 使用 Server SDK 5.0+,中继网络对服务端完全透明,服务器正常收发 UDP 即可。所有集成工作都在客户端和后端完成。

四、Ping Beacons:多区域延迟测量与最优放置

4.1 工作原理

Ping Beacons 提供了一种标准化的方式来测量客户端到各 Amazon GameLift Servers 区域的 UDP 延迟:

  1. 后端调用 ListLocations API 获取各区域的 ping 端点(域名 + 端口)
  2. 客户端并行向所有端点发送 UDP ping(每个端点 3 次取平均,总耗时约 3 秒)
  3. 延迟数据随 play 请求发送给后端
  4. 后端将延迟数据传给 StartGameSessionPlacement API,GameLift 据此选择最优区域

4.2 集成极简

Client SDK 中的 PingBeacons 是一个纯函数式工具,无状态、无副作用:

以下代码展示如何使用 PingBeacons 模块并行测量多区域延迟:

#include "gamelift/ping-beacons/PingBeacons.h"

std::vector<PingBeacons::PingEndpoint> endpoints = {
    {"us-west-2", "gamelift-ping.us-west-2.api.aws", 7770},
    {"us-east-1", "gamelift-ping.us-east-1.api.aws", 7770},
    {"eu-west-1", "gamelift-ping.eu-west-1.api.aws", 7770}
};

// 并行测量,约 3 秒完成
auto results = PingBeacons::MeasureLatencies(endpoints);

五、整体架构

下图展示了 Player Gateway 和 Ping Beacons 的端到端工作流程。整个架构涉及三个角色:游戏客户端、游戏后端和游戏服务器,各自承担不同的集成职责。

[图1]

完整的交互流程如下:

1. 游戏客户端启动后,向游戏后端请求 Ping Beacons 端点列表。后端调用 GameLift 的 ListLocations API 获取各区域的 UDP ping 端点地址。

2. 客户端收到端点列表后,使用 Client SDK 的 PingBeacons 模块并行向所有端点发送 UDP ping,每个端点测量 3 次取平均值,整个过程约 3 秒完成。测量结果上报给后端。

3. 后端将玩家的延迟数据传入 StartGameSessionPlacement API,GameLift 根据延迟数据自动选择最优区域创建游戏会话。

4. 游戏会话创建后,后端调用 GetPlayerConnectionDetails API,获取该玩家的中继端点列表(多个 IP:Port)和 Player Gateway Token。

5. 客户端通过 Client SDK 的 PlayerGatewayManager 连接中继端点。每个 UDP 包头部拼接 Token 后发送到中继端点,中继验证 Token 后剥离并转发给游戏服务器。游戏服务器正常收发 UDP,对中继网络完全无感知。

6. 客户端每 60 秒从后端刷新端点和 Token,同时 Client SDK 持续监控端点健康状态,自动切换不健康的端点,确保连接稳定性。

三个角色的职责划分:

角色 需要集成的 SDK 核心职责
游戏客户端 Client SDK(本项目) 端点选择、token 拼接、健康追踪、延迟测量
游戏后端 AWS SDK(boto3 / C++ SDK) 调用 GameLift API(GetPlayerConnectionDetails、StartGameSessionPlacement 等)
游戏服务器 无需额外集成 正常收发 UDP,中继对其透明

六、Client SDK 集成详解

6.1 添加到构建系统

Client SDK 零外部依赖,仅需 C++17 + 平台线程库。集成方式是直接复制源码到项目中:

以下 CMake 配置展示如何将 Client SDK 源码添加到项目构建系统中:

find_package(Threads REQUIRED)

add_library(gamelift_client_sdk
    src/gamelift/player-gateway/PlayerGatewayManager.cpp
    src/gamelift/player-gateway/PlayerGatewayFallbackAlgorithm.cpp
    src/gamelift/player-gateway/PlayerGatewayPredictiveRotationAlgorithm.cpp
    src/gamelift/ping-beacons/PingBeacons.cpp
)
target_include_directories(gamelift_client_sdk PUBLIC include)
target_link_libraries(gamelift_client_sdk PUBLIC Threads::Threads)

target_link_libraries(your_game_client PRIVATE gamelift_client_sdk)

6.2 客户端集成 Player Gateway

集成分为四步,对应 UDP 通信的完整生命周期:

6.2.1 第一步:初始化 PlayerGatewayManager

#include "gamelift/player-gateway/PlayerGatewayManager.h"
#include "gamelift/player-gateway/PlayerGatewayFallbackAlgorithm.h"

// 选择算法并初始化
playerGatewayManager->Init<PlayerGatewayFallbackAlgorithm>();

// 从后端获取连接详情后,注入端点和 token
playerGatewayManager->UpdateEndpointsAndToken(endpointUrls, base64Token);

6.2.2 第二步:修改 UDP 发送逻辑

// 原始逻辑:sendto(sock, data, len, 0, &serverAddr, addrLen);

// Player Gateway 逻辑:
auto endpoint = playerGatewayManager->GetHealthyEndpoint();  // 选择健康端点
auto modifiedData = playerGatewayManager->GetModifiedData(    // 拼接 token
    endpoint, originalData, dataLen);
sendto(sock, modifiedData.data(), modifiedData.size(), 0,
       &endpoint.address, endpoint.addrLen);                  // 发到中继端点

6.2.3 第三步:修改 UDP 接收逻辑

// 收到包后通知算法端点健康
playerGatewayManager->MarkEndpointReceived(sourceAddress);

// 将中继地址映射为 canonical 地址,让上层逻辑以为一直在跟同一个服务器通信
auto canonicalAddr = playerGatewayManager->GetCanonicalServerAddress(sourceAddress);

6.2.4 第四步:启动定期刷新

// 每 60 秒从后端获取最新端点和 token
playerGatewayManager->StartPeriodicUpdates([&]() {
    auto details = backend.GetPlayerConnectionDetails(sessionId, playerId);
    playerGatewayManager->UpdateEndpointsAndToken(
        details.endpoints, details.token);
}, 60);

6.3 后端集成

后端需要调用两个关键 GameLift API:

以下代码展示后端如何调用 GameLift API 创建游戏会话并获取连接详情:

// 1. 创建 Game Session 时传入延迟数据
Aws::GameLift::Model::StartGameSessionPlacementRequest request;
request.SetGameSessionQueueName("sample-app-queue-gateway");
for (const auto& latency : playerLatencies) {
    Aws::GameLift::Model::PlayerLatency pl;
    pl.SetPlayerId(playerId);
    pl.SetRegionIdentifier(latency.locationName);
    pl.SetLatencyInMilliseconds(latency.udpLatencyMs);
    request.AddPlayerLatencies(pl);
}

// 2. 获取连接详情(中继端点 + token)
Aws::GameLift::Model::GetPlayerConnectionDetailsRequest connReq;
connReq.SetGameSessionId(gameSessionId);
connReq.SetPlayerIds({playerId});
auto outcome = gameliftClient.GetPlayerConnectionDetails(connReq);
// 返回中继端点 IP:Port 列表和 base64 token

七、端点选择算法深度解析

Client SDK 内置两种算法,适用于不同游戏阶段。开发者也可以继承 PlayerGatewayAlgorithm 基类实现自定义算法。

7.1 Fallback 算法

策略:单端点使用,坏了才切换。

  • 始终只用一个”主端点”发送所有流量
  • 每次收到回包,重置健康倒计时(默认 2 秒)
  • 倒计时到期 → 认为端点失败 → 切换到下一个端点

时间线:

[图2]

适用场景:大厅、菜单、回合制游戏、统计界面等消息频率低的阶段。

7.2 Predictive Rotation 算法

策略:轮流使用所有端点,统计淘汰差的。

  • 每次发包 round-robin 到下一个端点
  • 时间分成 500ms 周期,统计每个端点收到的消息数
  • 周期结束时:低于最高值 50% 的端点标记为不健康,下个周期跳过

时间线(500ms 一个周期):

[图3]

适用场景:FPS、MOBA 等实时对战阶段(要求服务器每秒发送 30+ 条消息)。

7.3 动态切换

同一局游戏中可以根据阶段动态切换算法:

以下代码展示如何在游戏不同阶段动态切换端点选择算法:

// 开局:实时对战用 Predictive Rotation
manager->Init<PlayerGatewayPredictiveRotationAlgorithm>();

// 中场:统计界面切 Fallback
manager->SetAlgorithm<PlayerGatewayFallbackAlgorithm>();

// 下半场:切回 Predictive Rotation
manager->SetAlgorithm<PlayerGatewayPredictiveRotationAlgorithm>();

7.4 算法对比

Fallback Predictive Rotation
发送模式 单端点,坏了才切 轮流发到所有端点
健康判断 超时(默认 2s 没回包) 统计比较(消息数低于最高的 50%)
切换速度 被动,最慢 2s 主动,500ms 周期评估
流量分布 集中在一个端点 均匀分散到所有端点
端点暴露面 小(仅 1 个端点) 大(所有端点)
消息频率要求 服务器每秒 30+ 条

八、安全最佳实践

8.1 IAM 最小权限

后端运行所需的 GameLift 权限应遵循最小权限原则:

以下 IAM 策略展示后端运行所需的最小 GameLift 权限:

{
  "Effect": "Allow",
  "Action": [
    "gamelift:StartGameSessionPlacement",
    "gamelift:DescribeGameSessionPlacement",
    "gamelift:GetPlayerConnectionDetails",
    "gamelift:ListLocations"
  ],
  "Resource": "*"
}

CDK 部署额外需要 gamelift:CreateBuild、gamelift:CreateFleet、gamelift:CreateGameSessionQueue 等管理权限,建议与运行时权限分离。

8.2 不要暴露服务器 IP

Player Gateway 的核心价值是隐藏服务器 IP。后端在返回连接详情时,应该只返回中继端点,不要将 GetPlayerConnectionDetails 响应中的服务器 IP 泄露给客户端。

8.3 Keepalive 机制

客户端或服务器必须每 30 秒至少发送一个包以维持中继连接。对于回合制或有空闲期的游戏,需要实现心跳机制。

九、总结与展望

Amazon GameLift Servers 通过 Player Gateway 和 Ping Beacons 两项免费功能,为多人游戏提供了开箱即用的 DDoS 防护和延迟优化能力:

  • Player Gateway 通过中继网络隐藏服务器 IP、验证流量、自动切换不健康端点,且服务器端零改动
  • Ping Beacons 提供标准化的多区域 UDP 延迟测量,配合 GameLift 的放置算法实现最优区域匹配
  • Client SDK 零外部依赖,仅需 C++17,通过 PlayerGatewayManager 和 PingBeacons 两个核心类即可完成集成
  • CDK 部署 一键创建完整基础设施,支持 Gateway/Direct 双 Fleet 对比

对于 Unreal Engine 开发者,还可以使用 Amazon GameLift Servers Client SDK for Unreal Engine 插件,无需直接操作 C++ 层。

➡️ 下一步行动:

相关产品:

相关文章:

十、参考链接

*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。

本篇作者

万曦

亚马逊云科技解决方案架构师,负责基于亚马逊云科技的云计算方案的咨询和架构设计。坚实的 AWS Builder 文化拥抱者。拥有超过 12 年的游戏研发经验,参与过数个游戏项目的管理和开发,对于游戏行业有深度理解和见解。

汪允璋

亚马逊云科技解决方案架构师,目前专注于游戏行业云架构设计与优化,致力于帮助游戏客户应对高并发、全球部署及数据分析等技术挑战。

汤哲

亚马逊云科技行业解决方案架构师,负责基于 AWS 的云计算方案的咨询与架构设计,同时致力于 AWS 云服务知识体系的传播与普及。在软件开发、安全防护等领域有实践经验,目前关注游戏领域。


AWS 架构师中心:云端创新的引领者

探索 AWS 架构师中心,获取经实战验证的最佳实践与架构指南,助您高效构建安全、可靠的云上应用