最近英雄联盟手游(LOLM)可以玩了,出于好奇,对其中一些体验到的技术点做了简单分析。以下猜测基于客户端观察与流量实测。

引擎
Unity
网络同步
帧同步
测试设备
iPhone XS Max

帧同步快速恢复

现象 游戏后台 60 秒后回到前台,花费 14 秒快速运算追上最新帧,录像中可以明显看到整个游戏世界被加速。60 秒按 60 帧制约 3600 帧,14 秒跑完意味着单帧运算压到约 3.8ms

问题 若游戏已进行 20 分钟,按同样节奏恢复就需要约 4 分钟,体验相当差。由此引出两种可能的优化方向:

  1. 省略非必要计算恢复时省略不必要的流程(例如渲染),减小计算量、加快恢复速度。
  2. 服务端快照恢复服务端与客户端同步运算游戏逻辑(不只是广播帧操作),支持生成快照下发给客户端,客户端据此恢复,避免冗长的帧计算过程。

完全断线重连

现象 游戏进行 10 分钟时杀掉客户端进程,重新打开,从 loading 界面到能够继续游戏约 5 秒

分析 1 — 对应猜测 1(省略非必要计算)

假设 4 秒跑逻辑、1 秒收网络消息。逻辑以 20 帧运行,10 分钟共 1.2 万帧,单帧逻辑运算开销约 0.41ms(测试设备 iPhone XS Max)。基于这个数字可以进一步推测实现方式:

  1. 重 C# 实现(可能性较高)如果是重 Lua 开发模式,0.41ms 极难达到。猜测用 C# 实现了绝大部分战斗逻辑。即便如此,0.41ms 已经非常出色。
  2. 多核并行 + ECS(有可能)若 CPU 8 核且充分利用多核,单帧总运算量约 3.28ms,更符合历史开发经验。要高效利用 8 核且方案可工程化,首选 ECS(面向数据编程)框架。

分析 2 — 对应猜测 2(服务端快照恢复)

若服务端下发了一帧的快照,客户端依据快照恢复,5 秒绰绰有余。快照恢复最难的部分是客户端需要 100% 还原数据,连 vector 中元素顺序都不能变。若采用服务端同步运算方案,可以获得几个关键收益:

  1. 极速结算服务端同步运算,结算时估计 1 秒内即可得出战斗结果。若非同步运算,服务端校验就需从头跑完整局(估算约 10 秒)。实际体验中,结束动画播完到显示结算不到 1 秒。
  2. 外挂检测服务端同步运算意味着可以每 5 秒对关键逻辑做信息摘要与服务器对比,检测帧同步一致性、及早发现不同步。帧同步本身对大多数外挂天然防御——客户端只上传操作,比较难防的主要是透视。
  3. 快照调试快照除了用于恢复,对帧同步一致性排查同样有帮助。结合信息摘要对比,内网开发版甚至可以在每个函数入口都生成摘要做对比,精准定位不同步发生在哪一次函数调用之后——类似调试中的断点功能。

佐证:AI 托管

玩家掉线或长时间未操作后,该玩家会被 AI 托管自动游戏。至少有两种实现方案:

  1. 服务端同步运算服务端拥有完整游戏逻辑,直接输出 AI 操作。
  2. 委托正常客户端服务端不运算,AI 委托给某个正常客户端输出操作并上报。

若全部玩家都掉线后 AI 仍在托管,方案 2 就被否定——这反向佐证了服务端拥有完整游戏逻辑的同步运算模型。

双通道网络通信

游戏内双通道说明

客户端与服务器之间使用 WiFi 与移动网络双通道同时通信,同一消息可以双通道下发、客户端按消息编号去重。对这种方案的具体做法,有三种猜测:

  1. 同一消息双通道同时下发每个包都在动态选择最优通道,以局部最优实现全局最优。代价:服务器出口流量翻倍、客户端网络 CPU 开销翻倍,并且消耗玩家的移动网络流量。
  2. 按敏感度分流帧消息走双通道,非帧消息(聊天、地图标记等)走单通道节省流量;也可只让某个通道走单号帧来降低开销。核心是在流量开销与玩家感受之间寻找平衡点。
  3. 重传时启用双通道正常时走单通道,判断需要重传时启用双通道尽最大努力重传,恢复后回归单通道。可引入"主通道"概念,实时根据网络质量动态选择。实现难度最大。

将三种猜测按关键代价维度横向对比如下:

方案 实现难度 服务器出口流量 客户端 CPU 玩家移动流量
1 — 双通道同下发 翻倍 翻倍
2 — 按敏感度分流 仅帧消息翻倍 仅帧消息翻倍
3 — 按需启用(重传时) 基本正常 基本正常

流量测算与实测

假设帧同步 20 帧/秒、10 人同场,单客户端上传流量最大约 0.48 kb/s,下载约 4.8 kb/s。10 分钟战斗下载流量约 2.8 MB。实测结果如下:

通道模式时长流量消耗
WiFi 单通道18 分钟5 MB
移动网络单通道18 分钟4.2 MB(杀进程重连额外 +4.4 MB)
双通道15 分钟WiFi 4 MB + 移动 2.8 MB

关键发现 杀进程重连额外消耗约 4.4 MB,且游戏时间越长消耗越多——这几乎可以证明断线恢复是从第一帧重新运算到最新帧,而非基于快照恢复。结合实测流量,LOLM 的双通道方案更接近猜测 2 和猜测 3。

客户端登录请求频率限制

登录频率限制提示

服务器处理登录请求的开销相比其他请求要大得多,瓶颈主要有三处:

  • 数据加载从 DB 加载玩家数据到进程,Redis/MongoDB 较快,MySQL 更慢。
  • SDK 验证平台账号验证通过 HTTP 处理。实测:异步 IO 处理 HTTP 约 2000 条/s,Redis 约 2 万条/s,公网通信约 1.5 万条/s
  • 登录后流量激增活动数据、商城信息、好友列表、邮件推送等,登录后几秒内持续消耗 CPU。

应对突发情况,登录排队和限制登录时间间隔都是可行方案。在架构设计上,若将不同类型请求微服务化,应对手段会更丰富——服务降级、弹性伸缩等。

弱网表现

TODO 原本想在 PC 上用模拟器抓包并模拟弱网来深入分析,但 LOLM 不支持 Android 模拟器。后续计划在 PC 上搭建代理服务器,让手机经由 PC 代理再连接游戏服务器,这样就可以在 PC 端抓包和模拟弱网了。