惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

Airing 的博客

月刊(第34期):创造的快乐 2015-2016 随笔选集 2025,全新旅途 月刊(第33期):推理阶梯 月刊(第32期):中大校友会的采访 月刊(第31期):基于 Claude 的阅读流 月刊(第30期):写在 30 岁这天 游戏组件的一生: 从加载到上屏 月刊(第29期):新生活 2024,告别盛夏 月刊(第28期):AI 没有体验世界的能力 AI 心理疗愈应用的探索与实现 Mac 小众软件推荐与工作流分享(2024) 月刊(第27期):旅居 再见了,盛夏 Airing 开通了一个咨询服务 月刊(第26期):旅途 个人工具箱与好物分享 月刊(第25期):爱具体的人 2023,逃离仿徨 月刊(第24期):十年编程之路 月刊(第23期):多任务中的时间管理 月刊(第22期):当下的快乐 月刊(第21期):快节奏时代下的短视频 月刊(第20期):重启人生 月刊(第19期):日记的意义 大厂自研跨端框架技术揭秘 月刊(第18期):逃离社交网络 2022,平安喜乐 月刊(第17期):心之所向,素履以往 月刊(第16期):个人信息流分享 Chromium 渲染流水线——字节码到像素的一生 周刊(第13期):玄学杠杆与异世界小组 前端开发中的大小写敏感问题 周刊(第12期):前端三大浪漫 周刊(第11期):筮法是如何进行的 周刊(第10期):那些我喜欢的游戏(第1辑) 周刊(第9期):高效率到高消耗的现象与反思 周刊(第8期):三幕剧与英雄旅程 周刊(第7期):即兴发言模型 周刊(第6期):沟通艺术中的知觉检核 周刊(第5期):我在 TME 工作的一天 周刊(第4期):个人博客演变史 周刊(第3期):花束般的恋爱 周刊(第2期):重拾失去的好奇心 周刊(第1期):开刊,为什么写周刊 引擎剖析:JS 中的字符串转数值 2021,自渡向前 谈谈存在的价值与人生体验 Flutter 产物分析与减包方案 Roam Research 最佳实践——知识管理与任务管理 如何有效沟通——从《齐物论》立场问题切入 2020,追逐星火 《光·遇》之“禅” Flutter 核心原理与混合开发模式 Flutter 混合开发框架模式探索 Flutter Boost 混合开发实践与源码解析 2019,走走停停 React Hooks 源码解析(4):useEffect React Hooks 源码解析(3):useState React Hooks 源码解析(2): 组件逻辑复用与扩展 React Hooks 源码解析(1):类组件、函数组件、纯组件 WWDC19 游记 双生日记开发经验分享 前端安全 | HPP 的攻击举例与防范 前端安全 | XST 的攻击原理与防御 前端安全 | CSRF 的攻击手段与防范 前端安全 | XSS 的攻击手段与防范 人工意识何以可能? 文献阅读与论文写作的方法之己见 2018,沉淀初心 「没有你,也很好。」 Web 模拟终端博客系统 在线学习资源智慧推送系统研究 再见了,我的大学 6 万部豆瓣电影数据分析 B 站 2000 万用户分析
Flutter 异常处理方案——灰度与降级
2021-02-18 · via Airing 的博客

1. Flutter 异常概述

关于 Flutter 异常类型与捕获的文章网上已经有许多了,本文不再详细赘述,此处仅做个小结以保证文章的完整性。

Flutter 异常具体可分为以下几类:

  • Dart 异常
    • App 异常
      • 同步异常
      • 异步异常
    • Framework 异常
  • Engine 异常

所谓 Dart 异常,根据来源又可以细分为 App 异常和 Framework 异常,而 App 异常指的是。根据异常代码的执行时序,App 异常可以分为两类,即同步异常和异步异常:

  • 同步异常可以通过 try-catch 机制捕获
  • 异步异常则需要采用 Future 提供的 catchError 语句捕获

而在 Flutter 中提供了 Zone.runZoned 方法,在 Dart 中,Zone 表示一个代码执行的环境范围,类似于沙盒,可以使用其提供的 onError 回调函数来拦截所有未被捕获的异常。因为无论是同步异常还是异步异常都可以被拦截到,所以我们经常在 runApp 层来捕获所有的 App 异常。

runZoned<Future<Null>>(() async {
  runApp(MyApp());
}, onError: (error, stackTrace) async {
 //Do sth for error
});

所谓 Framework 异常,一般是Widget 在 build 时抛出的,其中默认的 ErrorWidget 就是开发时报错的红屏页面,它也支持被重写。

业务中,我们可以通过注册 FlutterError.onError 的回调来拦截 Flutter framework 外抛的异常:

FlutterError.onError = (FlutterErrorDetails details) {
	reportError(details.exception, details.stack);
};

所谓 Flutter Engine 异常,以 Android 为例就是 libflutter.so 发生错误,对应到 iOS 就是 Flutter.framework 发生错误,这部分的错误我们直接交给平台侧崩溃收集的 SDK 来处理,比如 firebase crashlytics、bugly 等,后文再详解。

2. 灰度策略

出于对线上业务的敬畏和某些运营要求,为了保障运营的稳定性,对于线上的 Flutter 业务,我们也需要提供一套较为完备的灰度策略和降级方案。首先,本小节中先谈谈灰度策略。

灰度的逻辑流程较为简单:配置灰度策略——后台下发配置&客户端加载配置——客户端处理配置。

2.1 灰度策略配置

我们在内部的配置平台上定义了一些 Flutter 灰度所需要的配置字段,具体包括:

  • key:对应的 Flutter 页面(route)
  • appkey:该配置对应的宿主 App
  • minVersion:最小生效版本
  • maxVersion:最大生效版本
  • type:灰度策略,具体包括尾号灰度,地域灰度,设备禁用,系统禁用,混合模式,白名单模式等,其中白名单模式出于测试考虑,混合模式则是支持配置各种策略取并集生效。
  • action:生效范围,如全量生效,全量不生效,灰度生效等。
  • url:降级的链接,支持参数替换符写法,客户端能够将 Flutter route 的入参拼接成 url query parameters。

2.2 后台下发与客户端加载配置

冷热启动都会拉配置,考虑到失败会有3次重试,本地会维护一份单例,在业务侧要打开 Flutter 页面时都需要检查灰度配置,来决定是否打开 Flutter 页面。 当然为了拉配置时防止 3 次重试都失败了,发版的时候本地会存一份各 Flutter 页面的降级配置 Map,极端场景下,会自动开启降级。

2.3 客户端处理配置

在业务侧要打开 Flutter 页面时都需要检查灰度配置,来决定是否打开 Flutter 页面。若判断非灰度,即命中降级,则拉配置的降级链接,配好 url 参数后使用 WebView 打开降级后的 H5。

需要注意的是,我们目前的业务基本都是 H5 改 Flutter,所以默认都有降级版本,而且降级版本的可靠性是可以保证的。对于未来只上 Flutter 的新业务,我们也正在预研 Flutter Web 的同构方案。

3. 降级方案

我们需要及时的降级来保证 Flutter 业务的可靠性,灰度和降级其实本质上都是来区分业务是使用 Flutter 还是 H5,只是前者是手动配置的,后者是自动生效的。在本地会维护根据 App 版本来维护一份降级配置,打开页面前会检查是否需要降级。有以下几种需要及时降级的场景:

3.1 未命中灰度降级

如前文所述,若业务方配置了灰度策略配置,在未命中灰度降级的场景下打开对应的 Flutter 页面,该页面需要降级并做上报。

3.2 框架异常降级

如果捕获到 Flutter Framework 异常,则将该页面置为「需要降级」,提供自定义的 ErrorWidget 提醒用户页面出错需要重新进入,之后在用户下次进入该页面时触发降级,定向到 H5 页面。

而对于 Dart 异常,由于Dart 采用事件循环的机制来运行任务,所以各个任务的运行状态是互相独立的。也就是说发生异常只会导致当前任务后续的代码不会被执行,用户仍可以继续使用页面中的其他功能,影响面不会太大,此处没有去强制降级处理,仅仅做了错误上报。

3.3 引擎崩溃降级

但如果是引擎发生了错误必定会导致 App Crash,这种情况下不仅需要上报日志,也会置好标志位,在用户下次打开 App 时不再启动 Flutter Engine,并全量降级 Flutter 所有页面。

3.4 产物加载失败降级

技术上我们使用了定制引擎并做了 Flutter 产物裁剪,每次发版时 App.framework 中会存一份对应的减包 zip 的 md5 值,在用户首次启动 App 时会下载减包产物再去启动引擎,之后校验产物完整性无问题后,定制引擎再去加载减包产物。但是存在着产物下载失败的情况,除了阶段性重试以外,这种情况也不能启动 Flutter Engine,并做所有页面的全量降级并上报。

3.5 Flutter 相关崩溃降级

除此以外,我们也遇到过 Flutter 导致的崩溃,不属于引擎崩溃也不是产物加载问题,也不是 Flutter 异常,仅仅是 Flutter Plugin 的问题,如插件原生侧的实现逻辑问题导致的崩溃,这也属于 Flutter 相关崩溃,但是在 Bugly 上报的日志中无法找到 Flutter 字样,因为程序退出时并非中断在 Flutter 内部或者引擎侧。

对于这种情况,我们会记录崩溃或 ANR 上报时的 topViewController 并溯源路径,如果当前路由栈内存在 Flutter Activity 或者 FlutterViewController,保险起见,发生崩溃依然降级。

4. 运营日报

Flutter 运营日报数据源为性能上报和异常上报。而至于崩溃的监控和告警,我们则交给了客户端的 Bugly 来处理了。日报记录了各 Flutter 页面在不同 App 版本的表现情况,有以下几个指标供读者参考:

  • pv
  • 访问成功率
  • Crash 率,Crash 影响用户数
  • 秒开率(300ms界限)
  • 降级率,灰度率
  • ……

最后,结合产物动态加载与降级策略的启动流程图如下所示:

启动流程图

参考文章