不断学习,做更好的自己!💪
视频号CSDN简书欢迎打开微信,关注我的视频号:程序员朵朵点我点我 一、前言- 稳定性很重要,Crash是P0优先级
- 稳定性可优化的面很广
1. 稳定性纬度
- Crash纬度
- 性能纬度:启动速度、内存、绘制等等优化方向,相对于Crash来说是次要的
- 业务高可用纬度
2. 稳定性优化概述
- 重在预防、监控必不可少
- 思考更深一层、重视隐含信息:如解决Crash问题时思考是否会引发同一类问题
- 长效保持需要科学流程
3. Crash相关指标
-
UV、PV PV(Page View):访问量 UV(Unique Visitor):独立访客,0 - 24小时内的同一终端只计算一次
-
UV、PV、启动Crash率 UV Crash率:针对用户使用量的统计,统计一段时间内所有用户发生崩溃的占比 Crash UV / DAU:评估Crash率的影响范围,结合PV 注意:沿用同一指标 PV Crash率:评估相关Crash影响的严重程度 启动Crash率:影响最严重的Crash,对用户伤害最大,无法通过热修复拯救,需结合客户端容灾 增量、存量Crash率:增量Crash是新版本重点,存量Crash是需要持续啃的硬骨头,优先解决增量、持续跟进存量
4. Crash率评价
- 必须在千分之二以下
- 万分位为优秀
5. Crash关键问题 尽可能还原Crash现场:
- 堆栈、设备、OS版本、进程、线程名、Logcat 前后台、使用时长、App版本、小版本、渠道 CPU架构、内存信息、线程数、资源包信息、用户行为日志
- Crash现场信息、Crash Top机型、OS版本、分布版本、区域 Crash起始版本、上报趋势、是否新增、持续、量级 根据以上信息决定Crash是否需要立马解决以及在哪个版本进行解决
- 参考Bugly平台的APM后台聚合展示
6. APM Crash部分整体架构 采集层
- 错误堆栈
- 设备信息
- 行为日志
- 其它信息
处理层
- 数据清洗
- 数据聚合
- 纬度分类
- 趋势对比
展示层
- 数据还原
- 纬度信息
- 起始版本
- 其它信息
报警层
- 环比:期与上一期进行对比
- 同比:如本月10号与上月10号
- 邮件
- IM
- 电话
责任归属
- 设立专项小组轮值
- 自动匹配责任人
- 处理流程全纪录
1. 单个Crash处理方案
-
根据堆栈及现场信息找答案 解决90%问题 解决完后需考虑产生Crash深层次的原因
-
找共性:机型、OS、实验开关、资源包,考虑影响范围
-
线下复现、远程调试
2. Crash率治理方案
-
解决线上常规Crash
-
系统级Crash尝试Hook绕过
-
疑难Crash重点突破或更换方案
3. Java Crash 出现未捕获异常,导致出现异常退出。
Thread.setDefaultUncaughtExceptionHandler();
我们通过设置自定义的 UncaughtExceptionHandler,就可以在崩溃发生的时候获取到现场信息。注意,这个钩子是针对单个进程而言的,在多进程的APP中,监控哪个进程,就需要在哪个进程中设置一遍ExceptionHandler。
获取主线程的堆栈信息:
Looper.getMainLooper().getThread().getStackTrace();
获取当前线程的堆栈信息:
Thread.currentThread().getStackTrace();
获取全部线程的堆栈信息:
Thread.getAllStackTraces();
第三方 Crash 监控工具如 Fabric、腾讯Bugly,都是以字符串拼接的方式将数组 StackTraceElement[] 转换成字符串形式,进行保存、上报或者展示。
4. Native Crash 特点:
- 访问非法地址
- 地址对齐出错
- 发送程序主动 abort
上述都会产生相应的signal信号,导致程序异常退出。
- 合格的异常捕获组件 一个合格的异常捕获组件需要包含以下功能:
- 支持在crash时进行更多扩张操作
- 打印logcat和日志
- 上报crash次数
- 对不同crash做不同恢复措施
- 可以针对业务不断改进的适应
- 现有方案
-
Google Breakpad 优点:权威、跨平台 缺点:代码体量较大
-
Logcat 优点:利用安卓系统实现 缺点:需要在crash时启动新进程过滤logcat日志,不可靠
-
coffeecatch 优点:实现简洁、改动容易 缺点:有兼容性问题
-
1. ANR 发生原因 没有在规定的时间内完成要完成的事情。
2. 发生场景
Activity onCreate方法或 Input 事件超过 5s 没有完成BroadcastReceiver前台 10s,后台 60sContentProvider在publish过超时 10s;Service前台 20s,后台 200s
3. 发生原因
- 主线程有耗时操作
- 复杂布局
IO操作- 被子线程同步锁
block - 被
Binder对端block Binder被占满导致主线程无法和SystemServer通信- 得不到系统资源(
CPU/RAM/IO)
业务高可用重要性
- 高可用
- 性能
- 业务
- 侧重于用户功能完整可用
- 真实影响收入
业务高可用方案建设
-
数据采集
-
梳理项目主流程、核心路径、关键节点
-
Aop自动采集、统一上报 -
报警策略:阈值报警、趋势报警、特定指标报警、直接上报(或底阈值)
-
异常监控
-
单点追查:需要针对性分析的特定问题,全量日志回捞,专项分析
-
兜底策略
-
配置中心、功能开关
-
跳转分发中心(组件化路由)
移动端容灾方案 灾包括:
- 性能异常
- 业务异常
传统流程: 用户反馈、重新打包、渠道更新、不可接受。
容灾方案建设:
-
功能开关 配置中心,服务端下发配置控制 针对场景:
- 功能新增
- 代码改动
-
统跳中心
- 界面切换通过路由,路由决定是否重定向
Native Bug不能热修复则跳转到临时H5页面
-
动态化修复
- 热修复能力,可监控、灰度、回滚、清除
-
推拉结合、多场景调用保证到达率
-
Weex、RN增量更新
-
安全模式 微信读书、蘑菇街、淘宝、天猫等“重运营”的
APP都使用了安全模式保障客户端启动流程,启动失败后给用户自救机会。先介绍一下它的核心特点:- 根据
Crash信息自动恢复,多次启动失败重置应用为安装初始状态 - 严重
Bug可阻塞性热修复
- 根据
-
安全模式设计 配置后台:统一的配置后台,具备灰度发布机制 1、客户端能力:
- 在
APP连续Crash的情况下具备分级、无感自修复能力 - 具备同步热修复能力
- 具备指定触发某项特定功能的能力
- 具体功能注册能力,方便后期扩展安全模式
2、数据统计及告警
- 统一的数据平台
- 监控告警功能,及时发现问题
- 查看热修复成功率等数据
3、快速测试
- 优化预发布环境下测试
- 优化回归验证安全模式难点等
- 在
天猫安全模式原理
1、如何判断异常退出?
APP启动时记录一个flag值,满足以下条件时,将flag值清空
APP正常启动10秒- 用户正常退出应用
- 用户主动从前台切换到后台
如果在启动阶段发生异常,则flag值不会清空,通过flag值就可以判断客户端是否异常退出,每次异常退出,flag值都+1。
2、安全模式的分级执行策略
分为两级安全模式,连续Crash 2次为一级安全模式,连续Crash 2次及以上为二级安全模式。
业务线可以在一级安全模式中注册行为,比如清空缓存数据,再进入该模式时,会使用注册行为尝试修复客户端 如果一级安全模式无法修复APP,则进入二级安全模式将APP恢复到初次安装状态,并将Document、Library、Cache三个根目录清空。
3、热修复执行策略
只要发现配置中需要热修复,APP就会同步阻塞进行热修复,保证修复的及时性
4、灰度方案
灰度时,配置中会包含灰度、正式两份配置及其灰度概率 APP根据特定算法算出自己是否满足灰度条件,则使用灰度配置
易用性考量
1、接入成本
完善文档、接口简洁
2、统一配置后台
可按照APP、版本配置
3、定制性
支持定制功能,让接入方来决定具体行为
4、灰度机制
5、数据分析
采用统一数据平台,为安全模式改进提供依据
6、快速测试
创建更多的针对性测试案例,如模拟连续Crash
异常熔断
多次请求失败则可让网络库主动拒绝请求
容灾方案集合路径
功能开关 -> 统跳中心 -> 动态修复 -> 安全模式
五、稳定性长效治理开发阶段
- 统一编码规范、增强编码功底、技术评审、
CodeReview机制 - 架构优化
- 能力收敛
- 统一容错:如在网络库utils中统一对返回信息进行预校验,如不合法就直接不走接下来的流程。
测试阶段
- 功能测试、自动化测试、回归测试、覆盖安装
- 特殊场景、机型等边界测试:如服务端返回异常数据、服务端宕机
- 云测平台:提供更全面的机型进行测试
合码阶段
- 编译检测、静态扫描
- 预编译流程、主流程自动回归
发布阶段
- 多轮灰度
- 分场景、纬度全面覆盖
运维阶段
- 灵敏监控
- 回滚、降级策略
- 热修复、本地容灾方案
1、你们做了哪些稳定性方面的优化?
Crash专项优化- 性能稳定性优化
- 业务稳定性优化
根据以上三方面的优化我们搭建了移动端的高可用平台。
2、性能稳定性是怎么做的?
- 全面的性能优化:启动速度、内存优化、绘制优化
- 线下发现问题、优化为主
- 线上监控为主
Crash专项优化
3、业务稳定性如何保障?
- 数据采集 + 报警
- 需要对项目的主流程与核心路径进行埋点监控,
- 同时还需知道每一步发生了多少异常,这样,我们就知道了所有业务流程的转换率以及相应界面的转换率
- 结合大盘,如果转换率低于某个值,进行报警
- 异常监控 + 单点追查
- 兜底策略
4、如果发送了异常情况,怎么快速止损?
- 功能开关
- 统跳中心
- 动态修复:热修复、资源包更新
- 自主修复:安全模式
Android 稳定性优化是一个需要长期投入,持续运营和维护的一个过程,只有深入了解这些底层知识,我们才能比别人设计出更好的稳定性优化方案。
