游戏服务器延迟高怎么解决?三种延迟的分类排查
「延迟高」是游戏运维里最含糊的一个说法。玩家说卡,你看监控一切正常;你测 ping 只有 30ms,玩家说他有 200ms。原因是「延迟」这个词在游戏里至少指三种完全不同的东西,混在一起就没法排查。
这篇按「先分类、再定位、后处理」的顺序讲。如果你还不确定是不是被攻击,先看卡顿还是被攻击那篇做判断。
第一步:分清三种延迟
| 类型 | 玩家感受 | 测量方式 | 正常值 |
|---|---|---|---|
| 网络延迟 | 操作有延迟、技能放出去慢半拍 | 游戏内 ping / tracert | 同省 <40ms,跨省 <80ms |
| 帧延迟 | 画面卡顿、掉帧,但操作响应正常 | 客户端 FPS 显示 | 稳定 60 以上 |
| 逻辑延迟 | 人和怪位置对不上、技能判定错位 | 服务端 tick 耗时 | 单帧 <16ms(60tick) |
三种的解决方向完全不同:网络延迟调线路,帧延迟优化渲染,逻辑延迟改服务端代码。搞错方向,花再多钱也没用。
转视角卡 = 帧延迟(客户端渲染问题)
转视角顺但走路卡 = 网络延迟或逻辑延迟
再看服务端 tick 耗时:正常就是网络问题,偏高就是逻辑问题。
网络延迟:按距离和线路排查
1. 物理距离绕不开
光在光纤里的速度大约是 20 万公里/秒。广州到北京直线 1900 公里,理论单程 9.5ms,往返 19ms。实际因为路由绕行,通常 35-50ms。
所以:
- 同省玩家 <40ms 是正常的
- 跨两三个省 50-80ms 正常
- 超过 100ms 就要查路由了
如果玩家分布在全国,单机房必然有一部分人延迟高。这不是优化能解决的,只能靠多节点。
2. 跨运营商是最大杀手
这是国内游戏延迟最常见的原因。玩家是电信,服务器在联通机房,晚高峰时段延迟能从 40ms 飙到 150ms。
判断方法:让玩家跑一下路由追踪:
# Windows
tracert 你的服务器IP
# macOS / Linux
traceroute 你的服务器IP
# 看哪一跳开始延迟暴涨,以及那一跳的运营商
# 电信 202.97.x.x / 联通 219.158.x.x / 移动 221.176.x.x
如果延迟在跨运营商的骨干节点(比如 202.97 开头)开始暴涨,就是跨网问题。
解决办法只有两个:
- 换 BGP 多线机房——机房同时接入电信、联通、移动,自动选路。成本比单线高 30-50%。
- 上加速节点——玩家就近接入,节点之间走内网专线。适合玩家分布广、又不想自己搞多机房的情况。
3. 晚高峰的出口拥塞
晚上 8-11 点是家庭宽带使用高峰,运营商出口拥塞,延迟和丢包都会上升。这个现象很典型:
- 白天正常,晚上卡
- 所有玩家同时出现,不分地区
- 丢包率明显上升(不只是延迟)
这不是你的问题,是运营商的问题。但如果你的机房线路质量差(比如小运营商、二级 ISP),受影响会更严重。
4. 服务端带宽跑满
带宽跑满会导致丢包,表现为延迟忽高忽低、玩家随机掉线。
查法:
# 看实时带宽占用
iftop -i eth0 -n
# 看丢包(在服务器上 ping 网关)
ping -c 100 网关IP | tail -3
# 看网卡错误计数(有 error/drop 就说明有问题)
ip -s link show eth0
如果带宽长期跑到 80% 以上,延迟一定不稳。要么升带宽,要么把静态资源(更新包、图片)挪到 CDN 上。
逻辑延迟:服务端代码问题
这类最容易被误判成「网络卡」,因为玩家感受也是「操作慢半拍」。
怎么确认是逻辑延迟
在服务端记录每帧的处理耗时。以 60 tick 为例,每帧预算 16.6ms:
# 简单的耗时打点
long t0 = System.nanoTime();
tick();
long cost = (System.nanoTime() - t0) / 1_000_000;
if (cost > 16) {
log.warn("tick 超时: {}ms, 在线人数 {}", cost, onlineCount);
}
如果这个日志经常出现,就是逻辑延迟。
常见的三个原因
| 原因 | 表现 | 处理 |
|---|---|---|
| 单线程瓶颈 | 在线人数一多就卡,CPU 单核跑满但总占用不高 | 分服、分场景、把 AI 和寻路拆到独立线程 |
| 数据库同步调用 | 玩家登录、充值、存盘时全服卡顿 | 改异步、加缓存、批量落盘 |
| GC 停顿 | 周期性卡顿(几秒一次),日志里有 Full GC | 调堆大小和 GC 参数,减少临时对象 |
GC 停顿最容易被忽略。表现是每隔几秒卡一下,玩家说「一卡一卡的」,但网络监控完全正常。查法:
# 开启 GC 日志
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log
# 看有没有 Full GC,以及停顿时间
grep "Full GC" gc.log | tail -20
帧延迟:客户端问题
这类和服务器无关,但玩家会一起归咎于「服务器卡」。
典型特征:
- 只有部分玩家卡(配置低的那些)
- 玩家说「画面卡但操作有反应」
- 降低画质设置后明显改善
如果确认是这类,能做的有限:优化资源加载、减少同屏对象、提供画质档位。这属于客户端优化范畴,不是运维能解决的。
按现象对照排查
| 现象 | 最可能的原因 | 先查什么 |
|---|---|---|
| 晚高峰才卡,白天正常 | 运营商出口拥塞 / 跨网 | 让玩家 tracert,看哪一跳爆 |
| 部分玩家卡,其他人正常 | 玩家所在地区线路差 | 统计卡顿玩家的运营商分布 |
| 所有人同时卡几秒 | GC 停顿 / 定时任务 | 服务端 GC 日志 |
| 在线人数越多越卡 | 单线程瓶颈 | 单核 CPU 占用、tick 耗时 |
| 延迟忽高忽低 + 掉线 | 带宽跑满 / 丢包 | iftop、网卡 error 计数 |
| 登录、充值时卡 | 数据库同步调用 | 慢查询日志 |
什么时候该上加速
如果排查完发现:
- 服务端 tick 正常、GC 正常、带宽没满
- 但玩家跨省、跨运营商的延迟还是高
- 而且玩家分布在全国各地
那这就是物理距离和线路的问题,靠优化代码解决不了。这时候要么自己搞多机房(成本高、运维复杂),要么用加速节点。
加速节点的原理很简单:玩家就近接入最近的节点(同省或同城),节点之间走运营商内网或专线,源站只和节点通信。这样玩家到节点是短距离,节点到源站是优质线路,两段加起来比直连快得多。
顺带的好处是源站 IP 不暴露,攻击者找不到真实服务器。这也是为什么游戏加速和游戏防护通常是同一套节点体系。
想了解节点是怎么工作的,看DDoS 防护原理。不确定自己的延迟问题属于哪一类,可以联系我们,把 tracert 和 tick 日志发过来帮你判断。