一次崩溃率暴涨 10 倍的线上事故:从“无堆栈”到精准定位,到光速解决

稳定性,是工程师的生存线。

我在团队中除了负责核心需求开发外,还负责技术创新(前文介绍的KMP)和性能优化(前文介绍的卡顿监控优化),稳定性等。这篇文章想聊一次我经历过的最棘手、最惊心动魄的线上稳定性事故。

它涉及:

  • SIGABRT / EGL_BAD_ALLOC / native 内存 OOM

  • 无业务堆栈、无 debug 信息

  • 大规模真实用户、不可回滚的线上互动功能

  • 多团队协作 & 错位 blame

  • 热修复策略受限 + 紧急曲线救国

更重要的是,如何从海量日志 + 极端场景 + 业务行为分析 中"抓到最后一根稻草",并把它证明成唯一真相。我负责项目的整体稳定性,Bugly 实时监控,Native 崩溃跟踪,灰度风险验证,历史问题溯源 & 定点治理。我每天到公司第一件事就是先看Bugly,跑我写的分析脚本,查看告警,了解我们的产品质量。

背景:直播互动场景复杂,稳定性责任重大

在我们教育直播 App 里,直播间有"小组讨论"场景:每个小组 6 人,平时只拉老师和课件流,老师触发互动 → 学生开始拉同组同学的音视频流,讨论结束 → 关闭拉流。看似普通需求,但它涉及动态 RTC 路径切换、频繁 Surface 创建/销毁、底层内存抖动

当问题发生时,我必须第一时间识别、定位、响应。

事故:崩溃率一天暴涨 10 倍

某天晚上正在写代码的我,收到了bugly的报警:App 崩溃率突然大幅跃升,且集中在同一直播课程类型。我们第二天的整体崩溃率直接拉升了10倍。 Bugly 报警如下:

ini 复制代码
SIGABRT

Failed to create context, error = EGL_BAD_ALLOC

-   0

    #00 pc 00000000000a8904 /apex/com.android.runtime/lib64/bionic/libc.so (abort+164) [arm64-v8a::a7f4c875f4091d6d01501d20016ac2a8]

-   11

    #11 pc 00000000000ac350 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) [arm64-v8a::a7f4c875f4091d6d01501d20016ac2a8]

堆栈近乎没有业务信息:一个字: 。我立马意识到,这不是常见的 Java OOM,而是: EGL_BAD_ALLOC = 显存/Surface 资源耗尽 → native OOM 。再结合 SIGABRT,非常明确:某个 native 资源未释放,导致 EGL 环境创建失败

但崩溃堆栈里没有明确业务代码,没有 RTC 相关调用,没有 Cocos 痕迹,没有崩溃上下文。这是最难排的一类事故:无栈 + native + 难复现

第一步:从日志里"复盘用户的一天"

我们有实时上传的全量日志 (自研接入链路),我抽取多个崩溃用户完整课时日志轨迹

包括session 行为序列,课程类型,设备内存变化,拉流与 Surface 生命周期,垃圾回收行为,CPU/MEM 峰值点

发现:

观察点 结果
崩溃设备 分散,无设备集中问题
发生场景 用户都做过新的互动(动态拉同组流,且互动了多次),还有Cocos题,H5互动题等
内存趋势 PSS 持续上升,峰值后立即崩溃
用户行为 不集中(说明不是单场景代码 crash)

第二步:锁定"共性" → 不断假设 &证伪

我第一时间把怀疑点定位到我们的新互动题上(拉关同组所有人视频流,且互动了多次)。我们业务的几个内存消耗大户,流媒体,Cocos互动题,H5互动题,以前都发生过较为严重的内存泄漏。因为我负责直播间的播放器和流媒体的开发,且新上线的这个互动和流媒体重度相关,所以第一时间拉流媒体老师排查。如果流媒体没问题,则下一步需要去找Cocos团队和FE团队确认业务变更。崩溃堆栈的不明确,给问题的解决带来了巨大困难。

我将崩溃日志按课堂维度进行聚类分析(我们业务规模足够大):

场景 崩溃比例
普通直播 几乎无崩溃
带小组讨论课堂 集中出现

这就让我意识到: 崩溃与小组音视频"动态拉流"强相关 。说明我刚开始的怀疑方向是对的。 这是典型内存泄漏 + 场景触发 + 极端堆叠

第三步:复现:一次复现就能锁死真凶

我用测试账号密集操作拉同组流这个互动 ,并观察:PSS 变化,Surface 数量,EGL context 数量,GPU 内存占用。最终成功复现: 每次互动讨论 → Surface 未释放 → 累计增长 → EGL 内存耗尽 → 崩溃。

抓到真凶了。

第四步:多团队共查 → 二分删代码确认

拉上流媒体负责人一起排查,是他们最近上线的一个拉流优化 导致:老师结束互动时,学生 Surface 对象没有释放 ,而这一优化是最近一个版本才上线,我们开发联调阶段根本没接到这段代码****

第五步:热修复?不够!只能曲线救国

问题出在 C++ 层,我们的热修复只能 patch Kotlin 层。怎么办?我想了一个策略,下发kotlin热修复包,更改互动逻辑。业务上层只拉用户音频流,不拉视频流。用户无感,虽然功能降级但彻底避免崩溃 同时:紧急修复bug, 小比例强升版本。针对课程粒度大规模推送。最终崩溃曲线极速回落

事故总结:定位思路与方法论

1. 先判断类型

EGL_BAD_ALLOC = GPU/Surface 泄漏

2. 用用户行为还原现场

日志复盘用户的行为

3. 找共性

跨用户 + 跨课程聚类

4. 激进复现

模拟真实课堂、重复操作

5. 找到"最后一根稻草

OOM 永远不是最终崩点,而是"积累崩溃模型"

6. 架构级降级策略

必要时牺牲体验换活着

教育直播类 App 稳定性体系

类目 手段
监控 Bugly、自研全量日志、PSS/Surface 监控、native signal 处理
定位 日志链路复原、行为聚类、设备维度剥离、二分验证
治理机制 Feature Flag、动态策略、灰度实验、强升
研发规范 RTC 场景 Surface 生命周期 checklist、C++ 资源自测脚本
演练 内存 stress 测试、极端设备测试、反复操作场景

特别适用于RTC + 多引擎 + 多端融合的业务场景。

崩溃率暴涨不可怕,可怕的是没有应对危机情况的能力

稳定性不是"碰运气",是系统工程,它涉及

  • 全链路监控
  • 行为洞察能力
  • 技术直觉
  • 极致复现
  • 果断降级
  • 多团队推动能力

这次经历让我更加深刻地理解:稳定性建设不是一次性的任务,而是一种长期的工程方法论。它要求我们在日常开发中不断思考、优化和预防,也促使团队形成科学的事故响应流程、复盘机制和可量化的稳定性指标。正是这种不断迭代和沉淀的能力,帮助我们在复杂业务场景下保持产品可靠,同时也提升了每一位工程师面对未知挑战时的判断力与执行力。

相关推荐
TDengine (老段)2 小时前
TDengine 字符串函数 TO_BASE64 用户手册
android·大数据·服务器·物联网·时序数据库·tdengine·涛思数据
spencer_tseng3 小时前
Eclipse Oxygen 4.7.2 ADT(android developer tools) Plugin
android·java·eclipse
来来走走4 小时前
Android开发(Kotlin) 协程
android·java·kotlin
河铃旅鹿5 小时前
Android开发-java版:Framgent
android·java·笔记·学习
2501_916008899 小时前
手机抓包app大全:无需root的安卓抓包软件列表
android·ios·智能手机·小程序·uni-app·iphone·webview
百锦再9 小时前
第18章 高级特征
android·java·开发语言·后端·python·rust·django
gcygeeker10 小时前
安卓 4.4.2 电视盒子 ADB 设置应用开机自启动
android·adb·电视盒子
小驰行动派10 小时前
安卓上的极简番茄钟 | 开源
android·开源
jzlhll12310 小时前
android抽屉DrawerLayout在2025的沉浸式兼容
android
基哥的奋斗历程10 小时前
Kotlin_Flow_完整使用指南
android·开发语言·kotlin