【AICon】AI 基础设施、LLM运维、大模型训练与推理,一场会议,全方位涵盖! >>> 了解详情
写点什么

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:002994

评论 2 条评论

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

FlutterAcitivty/FlutterController

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

极客时间架构训练营模块八作业

李晨

架构

面霸是怎样练成的?“2023”带你过关斩将,手撕面试官

钟奕礼

Java 程序员 java面试 java编程

大咖说·图书分享|深入浅出Node.js

大咖说

node.js

《Python编程:从入门到实践》有奖书评活动来啦!

图灵社区

事务

ssun

事务 JAV A 11月月更

2023跳槽一定不能错过的java面试集——前百度资深架构师整理

钟奕礼

Java 程序员 java面试 java编程

精彩回顾 | 苏州农商银行新一代云原生信息科技架构体系实践

BoCloud博云

云原生

如何拆掉跨部门的墙?

PMO实践

项目管理 企业管理 跨部门沟通

为啥PMO困惑的起因和其他职能部门不一样?

PMO实践

项目管理 PMO

瓴羊Quick BI企业数据分析工具,公司运营实时掌控

巷子

多场景下 3-11 倍性能提升,Apache Doris 1.2 新版本性能揭秘!

SelectDB

数据库 数据分析 Clickhouse Doris 数仓

欢迎航天宏图加入社区

openGauss

WebGL入门之基于WebGL的Sovit3D可视化平台

2D3D前端可视化开发

数据可视化 WebGL 三维可视化 web3d 3d绘图引擎

多云时代,如何构建配置管理数据库?

BoCloud博云

偶数层PCB板为何在PCB多层板中“独领风骚”?

华秋PCB

工艺 PCB PCB设计

openGauss的SQL引擎在3.1.0版本中做了哪些优化?

openGauss

海量数据 x 宝兰德 x openGauss Meetup成功举办,广州用户组正式成立!

openGauss

openGauss内核荣获中国首个国际CC EAL4+级别认证

openGauss

使用 Rainbond 搭建本地开发环境

北京好雨科技有限公司

Kubernetes rainbond

(Java开发岗)了解大厂面试基本套路及每一轮的重点

程序知音

Java 后端 java面试 java架构 互联网大厂面试

RocketMQ 客户端负载均衡机制详解及最佳实践

阿里巴巴云原生

阿里云 RocketMQ 云原生

租便宜的云服务器能干啥?有什么好处?怎么选择?

行云管家

云计算 服务器 云服务器

2022年中国新能源汽车出海市场发展洞察

易观分析

新能源汽车 出海

C语言学生管理系统

我是一个茶壶

C语言 学生成绩管理系统 11月月更

元年智答|数据洞察功能介绍

元年技术洞察

人工智能 数字化转型 智能

Java最常见的230道面试题,临阵磨枪,不快也光!涨薪指日可待

钟奕礼

Java 程序员 java面试 java编程

应用 Serverless 化,让业务开发心无旁骛

Serverless Devs

国密浏览器是什么?有哪些?有什么特点?

行云管家

国密 国密浏览器

从多个角度分析顺序表和链表区别和特点

C++后台开发

数据结构 算法 链表 linux开发 C++开发

openGauss 3.1.0的新型选择率模型大解密

openGauss

openGauss —— 智能优化器之基数估计

openGauss

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