可靠性是软件一个重要的质量属性, 它关注的是软件功能持续的可用性, 以及出现故障之后是否能够容错, 是否能快速的恢复使用.
可靠性六条基本准则
1, 故障应在第一时间被检测和感知;
2, 能避免的故障都不应该发生;
3, 不可避免或无法预测的故障, 需进行容错;
4, 已发生故障, 需在最短时间内得到恢复;
5, 对象状态和生命期都应该是完备的, 闭合的;
6, 资源必须合理和均衡地使用;
应用作为直接提供用户服务, 与用户交互最多的环节, 其可靠性对用户体验的影响巨大, 甚至会高于系统对用户造成的影响.
可靠性故障的现象及根因
应用不响应 (ANR)
(1) 应用将耗时操作或者同步调用放在 UI 线程, 广播接收器里处理;
(2) 应用资源异常, 如内存, 文件, 线程等的滥用, 泄露;
(3) 消息, 通知过载, 忙不过来;
(4) 获取系统资源阻塞, 比如访问文件系统, 数据库, 网络, CPU 等;
应用启动不起来, 界面卡住冻屏, 黑屏, 白屏
(1) 应用启动阶段必现闪退;
(2) 应用在启动阶段做了特殊的耗时, 阻塞动作;
(3) 应用事件处理 bug, 例如: 应用接收事件但不做任何响应;
(4) 应用资源异常, 获取系统资源阻塞;
(5) 应用窗口状态异常, 或者使用定制的显示绘制接口导致;
应用闪退或者频繁闪退
(1) 低级编码错误, 多线程并发错误, app 质量不合格;
(2) 异常处理不闭合, 不完备;
(3) 版本兼容性问题, 硬件兼容性问题;
Android 应用故障案例分享
一, 应用资源异常
1, 某输入法软件为了保证应用能常驻内存不被系统清理, 在应用进程退出时, 高频率注册 1 秒的定时器, 定时器到时候, 立即拉起该应用及关联应用. 如果系统反复清理该应用, 该应用会反复自启动, 导致系统卡顿很严重.
2, 某应用反复注册了 800 + 个应用权限管理的 AppOps Listener, 在执行 callback 的时候直接导致 system_server 进程的 global reference table overflow, 系统重启.
3, 某著名社交软件收到消息通知之前, 需要获取通话状态. 如果该应用短时间内收到通知消息特别多, 直接会将 system_server 的 binder 线程全部占满, 导致其他应用和服务无法与 system_server 通信, 直接导致系统重启.
二, 应用的特殊行为
1, 某社交软件在自身升级后的首次启动过程中, 长时间进入 dex2oat 优化过程, 应用界面显示黑屏. 按 back 键无效, 只能手杀, 大量用户反馈手机黑屏死机.
2, 某著名社交软件收到消息通知之前, 需要获取通话状态. 如果该应用短时间内收到通知消息特别多, 直接会将 system_server 的 binder 线程全部占满, 导致其他应用和服务无法与 system_server 通信, 直接导致系统重启.
3, 某应用注册加速度传感器以及近距离传感器监听的逻辑: 若两个传感器的注册有任何一个失败或者被拒, 则会进行无限重试, 直到两者全成功, 该逻辑会导致距离传感器被反复执行注册, 致使 system_server 的 fd 数量急速增加, 超过 1024, 导致 system_server 进程崩溃, 系统重启.
三, 兼容性问题
1,Google 版本升级导致. 应用升级 N 版本之后, 应用频繁闪退, 功能缺失, 应用无法使用, 清除数据和缓存也无效, 系统负载高, 用户退机.
2, 某应用推送最新版本异常. 应用升级之后, 用户无法使用.
3,ROM 升级之后, 导致应用无法使用. ROM 升级之后, 该应用读取电话薄失败, 应用频繁 Crash, 导致手机电话过程中无法挂断.
可靠性设计的一般准则
一, 业务功能的可靠性设计
1, 合理分配执行任务: 哪些放在前台? 哪些放在后台?
2, 仔细设计任务同步 & 并发: 采用同步还是异步? 多任务并发?
3, 任务负载的均衡: 多个业务执行流有序执行;
4, 对象生命周期的闭合;
5, 良好的用户交互和提示: 别让用户以为应用 crash
二, 应用数据源可靠性设计
1, 应用核心的数据 / 文件应有备份和容错设计
2, 来自外部输入设备的数据, 应用应能判别数据的合法性, 例如被破坏的数据源, 非法的外部数据 / 命令
3, 向外发起的服务请求, 要有超时和有限重试设计, 外部扰动不导致应用卡死
4, 外部发起的攻击性请求, 例如通知, 广播, 要有防护设计
三, 应用的资源可靠性设计
1, 分配的资源必须在确定的地方释放;
2, 使用资源必须有明确的上界, 如内存, 磁盘, 文件, 线程.
四, 优秀的编码能力
优秀的编码能力是应用可靠性设计的基础;
五, 完备的测试故障用例
事先考虑到应用内部, 外部可能发生的故障, 将故障的集合定义出来, 针对性的设计故障用例.
来源: https://juejin.im/post/5addaf55f265da0ba76f598b