HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

Flutter IM 跨端架构设计和实现

  • 2021-06-29
  • 本文字数:3461 字

    阅读完需:约 11 分钟

Flutter IM跨端架构设计和实现

现状

闲鱼 IM 框架构建于 2016-2017 年,期间多次迭代升级导致历史包袱累积多,后经 IM 界面 Flutter 化,造成架构更复杂,开发层面总结闲鱼当前架构主要存在如下几个问题:


• 研发效率较低:当前架构开发需求涉及到 Android/iOS 双端的逻辑代码以及 Flutter 的 UI 界面代码,定位问题往往只能从 Flutter UI 表象追查到 Native 逻辑漏洞;

• 架构层次较差:架构设计上分层不清晰,业务逻辑夹杂在核心的逻辑层致使代码变更风险大;

• 性能测试略差:核心数据源存储 Native 内存,需经 Flutter Plugin 将数据源序列化上抛 Flutter 侧,在大批量数据源情况下性能表现较差;

从舆情层面总结闲鱼 IM 当前架构的主要问题如下:

• 定位问题困难:线上舆情反馈千奇百怪,测试始终无法复现相关场景,因此很多时候只能靠现象猜测本质;

• 疑难杂症较多:架构不稳定性造成出现的问题反复出现,当前疑难杂症主要包括未读红点计数,iPhone5C 低端机器架构,以及多媒体发送等多个问题;

• 问题差异性大:Android 和 iOS 两端逻辑代码差异大,包括现存埋点逻辑都不尽相同,因此排查问题根源时候双端都会有不同问题根因,解决问题方案也不相同;

业界跨端方案

为解决当前 IM 痛点,闲鱼今年特起关于 IM 架构升级项目,重在解决客户端中双端一致性痛点,初步设想方案就是实现跨端统一的 Android/iOS 逻辑架构;在当前行业内跨端方案可初步归类如下图架构,在 GUI 层面的跨端方案有 Weex,ReactNative,H5,Uni-APP 等,其内存模型大多需要通过桥接到 Native 模式存储;在逻辑层面的跨端方案大致有 C/C++等与虚拟机无关语言实现跨端,当然汇编语言也可行;此外有两个独立于上述体系之外的架构就是 Flutter 和 KMM(谷歌基于 Kotlin 实现类似 Flutter 架构),其中 Flutter 运行特定 DartVM,将内存数据挂载其自身的 isolate 中;


null

考虑闲鱼是 Flutter 的前沿探索者,方案上优先使用 Flutter;然而 Flutter 的 isolate 更像一个进程的概念(底层实现非使用进程模式),相比 Android,同一进程场景中,Android 的 Dalvik 虚拟机多个线程运行共享一个内存 Heap,而 DartVM 的 Isolate 运行隔离各自的 Heap,因而 isolate 之间通讯方式比较繁琐(需经过序列化反序列化过程);整个模型如下图所示:


null

若按官方混合架构实现 Flutter 应用,开启多个 FlutterAcitivty/FlutterController,底层会生成多个 Engine,对应会存在多个 isolate,而 isolate 通讯类似于进程通讯(类似 socket 或 AIDL),这里借鉴闲鱼 FlutterBoost 的设计理念,FlutterIM 架构将多个页面的 Engine 共享,则内存模型就天然支持共享读取,原理图如下:


null

Flutter IM 架构设计

新老架构对比

如下图是一个老架构方案,其核心问题主要集中于 Native 逻辑抽象差,其中逻辑层面还设计到多线程并发使得问题倍增,Android/iOS/Flutter 交互繁杂,开发维护成本高,核心层耦合较为严重,无插拔式概念;


null


考虑到历史架构的问题,演进如下新架构设计


null


架构从上至下依次为业务层分发层逻辑层以及数据源层,数据源层来源于推送或网络请求,其封装于 Native 层,通过 Flutter 插件将消息协议数据上抛到 Flutter 侧的核心逻辑层,处理完成后变成 Flutter DB 的 Enitity 实体,实体中挂载一些消息协议实体;核心逻辑层将繁杂数据扁平化打包挂载到分发层中的会话内存模型数据或消息内存模型数据,最后通过观察者模式的订阅分发到业务逻辑中;Flutter IM 重点集中改造逻辑层和分发层,将 IM 核心逻辑和业务层面数据模型进行封装隔离,核心逻辑层和数据库交互后将数据封装到分发层的 moduleData 中,通过订阅方式分发到业务层数据模型中;此外在 IM 模型中 DB 也是重点依赖的,个人对 DB 数据库管理进行全面封装解,实现一种轻量级,性能佳的 Flutter DB 管理框架;

DB 存储模型

Flutter IM 架构的 DB 存储依赖数据库插件,目前主流插件是 Sqflite,其存储模型如下:


null


依据上图 Sqflite 插件的 DB 存储模型会有 2 个等待队列,一个是 Flutter 层同步执行队列,一个是 Native 层的线程执行队列,其 Android 实现机制是 HandlerThread,因此 Query/Save 读写在会同一线程队列中,导致响应速度慢,容易造成 DB SQL 堆积,此外缺失缓存模型,于是个人定制如下改进方案:


null

Flutter 侧通过表的主键设计查询时候会优先从 Entity Cache 层去获取,若缓存不存在,则通过 Sqflite 插件查询,同时改造 Sqflite 插件成支持 sync/Async 同步异步两种方式操作,对应到 Native 侧也会有同步线程队列和异步线程队列,保证数据吞吐率;但是这里建议查询使用异步,存储使用同步更稳妥,主要怕出现多个相同的数据元 model 同一时间进入异步线程池中,存储先后顺序无法有效的保证;

ORM 数据库方案

IM 架构重度依赖 DB 数据库,而当前业界还没有一个完备的数据库 ORM 管理方案,参考了 Android 的 OrmLite/GreenDao,个人自行设计一套 Flutter ORM 数据库管理方案,其核心思想如下:


null

由于 Flutter 不支持反射,因此无法直接像 Android 的开源数据库方式操作,但可通过 APT 方式,将 Entity 和 Orm Entity 绑定于一身,操作 OrmEntity 即操作 Entity,整个代码风格设计也和 OrmLite 极其相似,参考代码如下:


null

IM 内存数据模型

FlutterIM 架构在内存数据模型主要划分为会话和消息两个颗粒度,会话内存数据模型交托于 SessionModuleData,消息内存数据模型交托于 MessageModuleData;会话内存数据有一个根节点 RootNotice,然后其挂载 PSessionMessageNotice(这里 PSessionMessageNotice 是 ORM 映射的会话 DB 表模型)子节点集合;消息内存数据会有一个 MessageConatiner 容器管理,其内部挂载此会话中的 PMessage(PMessage 是 ORM 映射的消息 DB 表模型)消息集合。


依据上一章节,PSessionMessageNotice 设计了一个 OrmEnitity Cache,考虑到 IM 中会话数是有限的,因此 PSessionMessageNotice 都是直接缓存到 Cache 中,这种做法的好处是各地去拿会话数据元时候都是缓存中同一个对象,容易保证多次重复读写的数据一致性;而 PSessionMessageNotice 考虑到其数量可以无限多的特殊性,因此这里将其挂载到 MessageContainer 的内存管理中,在退出会话的时机会校验容器中 PMessage 集合的数量,适当缩容可以减少内存开销,模型如下图所示:


null

状态管理方案

Flutter IM 状态管理方案比较简单,对数据源 Session/Message 维度使用观察者模式的订阅分发方式实现,架构类似于 EventBus 模式,页面级的状态管理无论使用 fish-redux,scopeModel 或者 provider 几乎影响面不大,核心还是需保留一种插拔式抽象更重要;架构如下图:


null

IM 同步模型方案

如下是当前现状的消息同步模型,模型中存在 ACCS Thread/Main Thread/Region Thread 等多线程并发场景,导致易出现多线程高并发的问题;native 的推送和网络请求同步的隔离方案通过 Lock 的锁机制,并且通过队列降频等方式处理,流程繁琐且易出错。整体通过 Region Version Gap 去判断是否有域空洞,进而执行域同步补充数据。


null

改进的同步模型如下,在 Flutter 侧天然没多线程场景,通过一种标记位的转化同步异步实现类似 Handler 消息队列,架构清晰简约了很多,避免锁带来的开销以及同步问题。


null

进展以及性能对比

• 针对架构层面:在 FlutterIM 架构中,重点将双端逻辑差异性统一成同一份 Dart 代码,完全磨平 Android/iOS 的代码差异性带来的问题,降低开发维护,测试回归,视觉验收的一半成本,极大提高研发效率;架构上进行重构分层,实现一种解耦合,插拔式的 IM 架构;同时 Native 到 Flutter 侧的大量数据上抛序列化过程改造成 Flutter 引用传递,解决极限测试场景下的私聊卡顿问题;

• 针对线上舆情:补齐 UT 和 TLog 的集团日志方式做到可追踪,可排查;另外针对于很多现存的疑难杂症重点集中专项解决,比如 iphone5C 的架构在 Flutter 侧统一规划,未读红点计数等问题也在架构模型升级中修复,此外多媒体音视频发送模块进行改造升级;

• 性能数据对比:当 IM 架构的逻辑层和 UI 层都切换成 Flutter 后,和原先架构模式初步对比,整体内存水位持平,其中私聊场景下小米 9 测试结果内存下降 40M,功耗降低 4mah,CPU 降低 1%;极限测试场景下新架构内存数据相比于旧架构有一个较为明显的改观,主要由于两个界面都使用 Flutter 场景下,页面切换的开销降低很多;

展望

JS 跨端不安全,C++跨端成本有点高,Flutter 会是一个较好选择;彼时闲鱼 FlutterIM 架构升级根本目的从来不是因 Flutter 而 Flutter,是由于历史包袱的繁重,代码层面的维护成本高,新业务的扩展性差,人力配比不协调以及疑难杂症的舆情持续反馈等等因素造成我们不得不去探索新方案。经过闲鱼 IM 超复杂业务场景验证 Flutter 模式的逻辑跨端可行性,闲鱼在 Flutter 路上会一直保持前沿探索,最后能反馈到生态圈;总结一句话,探索过程在于你勇于迈出第一步,后面才会不断惊喜发现


本文转载自:闲鱼技术(ID:XYtech_Alibaba)

原文链接:Flutter IM跨端架构设计和实现

2021-06-29 07:003220

评论 2 条评论

发布
用户头像
有兴趣卖解决方案吗,关于移动端的,我们是华东院的
2021-09-17 13:51
回复
用户头像
xxxx

FlutterAcitivty/FlutterController

2021-07-01 18:18
回复
没有更多了
发现更多内容

你知道微服务架构中的“发件箱模式”吗

JAVA旭阳

Java 架构

Button(按钮)与ImageButton(图像按钮)

梦笔生花

Android Studio button imagebutton

分享 7 个不错的 AI 工具

devpoint

人工智能 AI openai

MySQL字符集和排序规则详解

C++后台开发

MySQL 数据库 中间件 后端开发 C++开发

盘点毫末智行AI DAY:智算中心成立、六大闭环、MANA五大模型...助力毫末智能驾驶产品快速迭代

科技大数据

使用 OpenAI ChatGPT 进行了编码尝试

devpoint

人工智能 openai ChatGPT

选购LED显示屏时需要注意8个技术参数

Dylan

LED显示屏 户外LED显示屏 led显示屏厂家

Guitar Pro2024最新免费版吉他打谱软件下载

茶色酒

Guitar Pro Guitar Pro8 guitar pro2023

社交视频直播一对一交友APP源码之Android如何打包APP

山东布谷科技胡月

语音直播app开发

TSDB助力井下位置服务

CnosDB

数据库 IoT 时序数据库 开源社区 infra

高并发系统设计的15个锦囊

小小怪下士

Java 程序员 系统设计 高并发

用 SwiftUI 实现 AI 聊天对话 app - iChatGPT

37手游iOS技术运营团队

ios SwiftUI openai ChatGPT

【Redis技术探索】「数据迁移实战」手把手教你如何实现在线+离线模式进行迁移Redis数据实战指南(在线同步数据)

洛神灬殇

redis 数据同步 1月日更 数据同步工具 RedisShake

直播交友一对一视频语音APP项目系统架构和模式分析(成品1对1源码)

山东布谷科技胡月

视频语音直播app开发 语音直播交友系统搭建 社交app开发 1v1语音系统搭建 视频社交APP开发

干掉 “重复代码”,这三种方式绝了!

风铃架构日知录

Java 程序员 码农 工程师 代码

如何使用Gradle构建一个多模块项目?

风铃架构日知录

Java 程序员 后端 码农 架构师

线上压测

agnostic

极客时间运维进阶训练营第十周作业

老曹

EditText(输入框)详解

梦笔生花

android edittext 输入框设计 文本框(TextView)

2023-01-06:给定一个只由小写字母组成的字符串str,长度为N, 给定一个只由0、1组成的数组arr,长度为N, arr[i] == 0表示str中i位置的字符不许修改, arr[i] ==

福大大架构师每日一题

算法 rust Solidity 福大大

如何告别丑陋判空?一个Optional类就能搞定!

风铃架构日知录

Java 程序员 程序人生 后端 码农

Smart Finance成为火必投票竞选项目,参与投票获海量奖励

鳄鱼视界

分享 7 个VUE项目用得上的JavaScript库

devpoint

JavaScript Vue 前端开发 前端开发框架

Portraiture4人像智能磨皮插件下载亲测可用

茶色酒

Portraiture2023 Portraiture

使用 App Store Connect API 批量创建内购商品

37手游iOS技术运营团队

AppleParty 苹果派 App Store Connect API 批量创建内购IAP 批量上传 IAP

数字人民币创新浪潮来袭,支付机构如何“乘风破浪”?

易观分析

金融 数字人民币 数字支付

推动GameFi走向新叙事的Smart Finance,成为火必投票竞选项目

股市老人

8 个很酷的 GitHub 技巧

devpoint

GitHub vscode 开发技巧

如何让你的架构设计应用做到高内聚、低耦合?

风铃架构日知录

Java 程序人生 后端 架构设计 后端开发

OpenTelemetry日志体系

骑牛上青山

Java 日志 log 调用链 OpenTelemetry

Flutter IM跨端架构设计和实现_大前端_闲鱼技术_InfoQ精选文章