游戏服务端进程异常退出排查,难点往往不是缺少日志,而是应用、操作系统和进程管理器记录的时间与信息彼此分散。先固定异常发生的时间范围,再将告警、退出码、系统事件和崩溃转储对齐,通常能较快区分程序崩溃、内存耗尽、人工终止和依赖故障。
先用告警锁定异常窗口
收到进程退出或实例重启告警后,先记录服务名称、实例标识、告警时间及最近一次健康检查成功时间。把查询范围扩展到故障前后数分钟;如果日志采集存在延迟,应以日志中的事件时间为准,不要只看平台的接收时间。
随后核对心跳探针、请求错误率、内存和 CPU 曲线,以及进程重启次数。心跳中断但进程仍在,可能是线程卡死或网络阻塞;进程已退出且重启次数增加,则应继续查找终止原因。单独依据一次延迟升高,不能断定进程已经崩溃。
按顺序串联三类证据
- 检查应用日志:按服务实例和时间筛选最后数十条记录,重点找未捕获异常、断言失败、配置解析错误,以及关停或重启提示。确认日志是否在退出前及时写入,缓冲区未刷盘可能让末尾信息缺失。
- 读取退出状态和管理器记录:在 Linux 上查看 systemd 日志与服务状态,例如使用 journalctl 按服务和时间范围过滤。记录退出码、信号以及是否由 systemd 自动重启。信号 11 常与非法内存访问有关,信号 6 常见于主动终止进程;退出码 137 常对应以 SIGKILL 结束,但不能仅凭它认定是 OOM。
- 核对操作系统事件:检查内核日志是否记录 OOM Killer 终止进程,并对照同一时段的内存压力、容器限制和其他进程变化。若运行在 Windows,检查事件查看器中的应用程序错误和 Windows 错误报告记录;Linux 与 Windows 的日志位置和字段不同,按实际部署环境查证。
- 分析崩溃转储:若有 core 文件,可用 coredumpctl 查找对应进程,并用 gdb 查看栈回溯。分析时保留与线上二进制匹配的调试符号;版本不一致时,函数名和行号可能不可靠。
根据证据缩小原因范围
程序自身崩溃
若应用日志出现异常,而转储中的栈回溯指向相同模块,先核实发布版本、配置变更和相关代码路径。将崩溃时间与构建号、地图或资源加载记录关联,比较故障实例与正常实例的差异。没有转储时,先启用受控的崩溃转储采集,并确认磁盘空间、文件权限和保留周期。
资源耗尽或外部终止
若内核记录 OOM Killer,检查进程的实际内存占用、容器内存上限及同机负载;如果没有 OOM 证据,再查部署平台、运维操作和进程管理器日志,确认是否收到停止信号。资源曲线应覆盖故障前一段时间,采样过稀可能错过短暂峰值。
游戏服务端进程异常退出排查应保留证据链:告警时间对应监控曲线,进程退出状态对应系统记录,代码级原因对应日志或转储。三者缺一时,结论就应标记为待验证,而不是把时间上的巧合当成根因。
让下一次告警更有用
- 为日志加入统一的 UTC 时间、实例标识、构建版本和请求或会话关联标识;避免记录玩家密码、令牌等敏感信息。
- 将进程存活、健康检查失败、重启次数和资源压力设为不同告警,明确每条告警代表的现象,避免把自动重启误报为根因。
- 限制崩溃转储的访问权限并设置保留策略;转储可能包含内存中的敏感数据,不宜无限期保存或公开传输。
- 每次修复后记录复现条件、证据和验证结果。游戏服务端进程异常退出排查的记录越完整,后续越容易区分重复故障与新问题。
常见问题
只有重启告警,没有崩溃日志怎么办?
先查进程管理器和操作系统日志,再确认应用日志是否因缓冲未写入。随后检查崩溃转储是否启用及是否有权限生成。
退出码 137 是否一定表示内存不足?
不是。它常表示进程收到 SIGKILL,但手动终止、管理器强制停止等也可能造成相同结果。需结合内核和管理器记录判断。
日志与告警时间相差较大,该信谁?
先统一时区,并比较事件发生时间与采集时间。检查主机时钟同步和采集延迟后,再用实例标识及事件顺序交叉验证。
没有调试符号还能分析转储吗?
仍可查看部分地址和线程信息,但难以可靠定位函数与源码行。应保存与线上构建对应的二进制及符号文件。