厦门游戏后端阿哲:用 Base85 压协议报文,每日 2.3 万条日志从 18 分钟缩到 4 分钟,省下 1 次带宽超支
2026 年 9 月 18 日晚上十一点,厦门软件园二期的工位上,阿哲盯着监控面板上那条黄色告警线,手里捏着一罐已经放温的咖啡。他负责的是一款日活 6 万的休闲手游后端,当天日志上传量又顶到了云存储的免费额度边缘。运维在群里丢了一句:“再超就按阶梯价收,下个月预算自己想办法。”阿哲面前摆着两个选择:要么把日志级别调低,以后出问题只能靠猜;要么换一种更紧凑的编码方式,把同样多的信息塞进更小的体积里。他选了后者。
之前是怎么扛的
阿哲的日志链路不复杂:游戏服把关键协议报文和错误堆栈序列化后,用 Base64 编码成纯文本,再推给日志平台。问题出在 Base64 的膨胀率——每 3 个字节变成 4 个字符,体积固定多出约 33%。
他算过一笔账:每天 2.3 万条日志,原始二进制大概 1.1 GB,Base64 之后接近 1.5 GB。云存储按量计费,超出免费额度的部分每月多掏 280 元左右。钱还不是最疼的,疼的是排查。每次线上出问题,他得从日志平台把 Base64 串导出来,本地写脚本解码,再对着时间戳一条条翻。一次典型的故障定位,光解码和格式化就要 18 分钟,赶上大促当晚出问题,这 18 分钟足够让客服电话被打爆。
更隐蔽的代价是带宽。今年 7 月一次版本更新后日志量翻倍,上传任务把出口带宽占满,游戏服的实时同步延迟跟着抖了 40 毫秒,玩家在论坛里骂“走路回弹”。阿哲事后复盘,根子就在编码膨胀上。
换了之后真实变了什么
9 月下旬,阿哲把日志编码从 Base64 换成了 Base85。他用的就是 Base85/Ascii85/Z85 编码工具,同一个二进制块丢进去,输出比 Base64 短一截。原理不玄乎:Base85 用 85 个可打印字符表示数据,每 4 个字节编成 5 个字符,膨胀率约 25%,比 Base64 的 33% 少了 8 个百分点。
别小看这 8 个点。他拿 9 月 20 日到 26 日一周的真实日志做了对比:
- 体积:Base64 编码后日均 1.48 GB,Base85 编码后日均 1.37 GB,每天省下约 110 MB。一个月下来存储和带宽费用从 280 元降到 190 元,省了 90 元。
- 时间:以前排查一次故障,导出、解码、格式化平均 18 分钟;现在日志平台直接按 Base85 解码展示,他只需要核对时间戳和堆栈,平均 4 分钟。按每周 3 次排查算,一个月省下近 3 小时。
- 带宽:上传任务占用的出口带宽峰值降了约 7%,10 月大促当晚实时同步延迟稳定在 12 毫秒以内,没再出现回弹投诉。
换的过程中也踩了两个小坑。第一个是字符集兼容:Base85 有多个变体,Adobe 的 Ascii85 用 <~ ~> 做定界符,git 用的变体不带定界符,ZeroMQ 的 Z85 又要求输入长度是 4 的倍数。阿哲第一次批量转换时混用了变体,日志平台解出来一堆乱码。他的解决办法是固定用 Z85 变体,并在转换前加一步长度补齐,把不足 4 字节的块补零再编。第二个坑是部分老日志的编码标记没更新,平台按 Base85 去解 Base64 的老数据,报了一晚上错。他后来在日志头里加了一个 2 字节的编码标识位,新旧数据分开处理,问题就没了。
给同样处境的人提个醒
如果你也在为日志或协议报文的体积发愁,Base85 值得试,但别指望它包治百病。它省的是 8 个百分点左右的膨胀,数据本身该多大还是多大,真要压缩得配合 gzip 一起用。另外,选变体之前先确认你的下游系统认哪一种,Adobe、git、ZeroMQ 三套字符集不通用,混用比不换还麻烦。最后,编码标识位这种小事别省,新旧数据并存的时候,它能帮你省掉一整晚的排错。