NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

Flutter Worker —— 闲鱼这样实现“逻辑跨平台”

  • 2021-03-18
  • 本文字数:3191 字

    阅读完需:约 10 分钟

Flutter Worker —— 闲鱼这样实现“逻辑跨平台”

闲鱼社区主要页面采用 Native 实现,部分使用 Flutter 和 Weex 承接。帖子、话题等固定数据结构的处理,点赞、评论等用户交互和状态同步,这些数据逻辑大部分是重复的,而且在多技术栈实现性价极低。由此我们想,能否在端上实现这样的一套工具,解放劳动力的同时,摆脱对服务端 BFF 层的依赖,保证研发效能。


抽象地看,实际上我们需要的正是一个逻辑跨平台工具。逻辑跨平台概念由来已久,也有一些很优秀的方案可以参考:

  • C++语言在 Objective-C/Java 等 Native 语言都有成熟接口可以调用,这使得 C++有天然的跨平台优势。同时不可否认的,C++入门门槛会比较高,导致后期维护成本大。

  • KMM 是 JetBrains 推出的用于跨平台移动开发 SDK,提供了一个语言级别的逻辑跨平台解决方案,可以将直接代码编译为与目标平台完全相同的格式。

结合团队内现有的一些技术基建,最终我们使用 Dart 完成了这一设计,在不同平台保证数据和逻辑处理的一致性,节约人力资源的同时保证用户体验。取名 Flutter Worker。

整体架构设计

在进行整体的设计之前,首先限定 worker 的业务场景:目标是提供一个多端可复用的逻辑处理中心,端上发起数据请求,所有的逻辑处理在 FlutterWorker 收口,执行完成返回回调给端上。设想中,在 worker 写 Handler 只需要关注逻辑处理,对于数据的传入和在端上的接收,开发者只需要指定类型,worker 会自动把数据转化成该类型。


由此,在整体的架构设计中,我们主要考虑以下几个方面:

  • FlutterWorker 需要一个稳定的运行环境,由于涉及到数据处理等可能会比较耗时的操作,需要保证不影响 UI 界面的绘制。

  • 处理后的数据要供给多端使用,数据结构必须对齐。

  • 提供足够的切面,方便接入方拓展。

  • 为了保证运行时稳定可靠,需要添加监控及时发现问题,并且在上线前时,对性能进行测试评估。


整体的架构图如下:


null


  • 运行容器层:容器是 worker 运行的基础,在保证性能的前提下,要尽可能的利用闲鱼现有的技术基建。

  • 状态管理层:worker 在这里完成数据的存储和状态的同步。端上存储状态数据,通过订阅状态消息来接收数据的变动。考虑到状态管理层在目前没有业务的强需求,这部分仅停留在 Demo 阶段还未落地,后面不再进行阐述。

  • 数据处理层:包含了 worker 所有的中间层数据处理部分,主要包括 Model 对象同步、数据转换和数据类型同步。基础数据类型在 Dart 语言中天然支持,在 iOS 端 Androiddr 端都有对应的类型,因此,worker 工作主要在后两者。

  • 监控层:worker 在线上运行,需要有监控来保障,及时发现问题及时响应。


下面对各个模块进行详细的介绍。

运行容器层

FlutterWorker 的运行环境强依赖 FlutterEngine 和 Isolate,从这个角度来考虑,对以下三种方案做了梳理和对比。


值得一提的是,随着 Flutter2.0 推出,我们在更新日志中注意到有一项对多开 Flutter Engine 实例内存消耗的优化。据官方文档称,额外 Flutter 引擎的静态内存占用量降低了约 99%,使每个实例的占用量大约为 180KB。结合源码来看,这里是新提供了 FlutterEngineGroup 类来创建 Flutter Engine。


null


相较于原来的 API,FlutterEngineGroup 生成的 FlutterEngine 具有常用共享资源(例如 GPU 上下文、字体度量和隔离线程的快照)的性能优势,从而加快首次渲染的速度、降低延迟并降低内存占用。


同时 EngineGroup 本身和其生成的 FlutterEngine 不需要持续保活,只要有 1 个可用的 FlutterEngine,就可以随时在各个 FlutterEngine 之间共享资源。EngineGroup 销毁后,已生成的 FlutterEngine 也不受影响,只是无法继续在现有共享的基础上创建新引擎。


虽然现在 FlutterEngineGroup 还不是一个稳定 API,但是这为 FlutterWorker 提供了另一种可能。综合考虑,目前实现选择了方案 3 来实现。

数据处理层

从用户调用开始,worker 的数据流图如下图所示:

null

数据在三端的流通,是通过调用 NatiaveWorker,执行到对应的 WorkerHandler,处理完成后再以异步的方式回调到 Native 方法。中间主要涉及 Model 对象同步和数据转换过程,worker 对这里分别实现了处理库。

Model 对象同步

worker 首先要实现的是,是 OringinDataModel ==> TargetDataModel。TargetDataModel 的定义在 iOS/Android/Flutter 三端的表现形式要保持一致,直接用代码生成是最好的选择。这里参考一些硬件协议,指定 IDL 格式来生成三端 Model 并导入工程。封装的 dartGen 库可以解析这些 yaml 节点,生成我们需要的胖 Model。


null


方便开发者使用,dartGen 打包成了 cli 工具。模仿 GsonFormat 插件,json 数据在 IDE 中可以方便转成对应的 dartGen 可以解析的 yaml 协议。对于其他生成 Model 的需求,可以以很小的代价修改模板,定制化高。

数据转换

通过 Flutter 的 MethodChannel 向 Native 传输数据,需要经过一层 messager 编码,而且编码数据为基础类型。所以在 BinaryMessager 的基础上,封装了 WorkerBinaryMessenger 方便做定制化处理。

iOS 端和 Android 端有成熟的 model 转换库(YYModel 和 FastJson)。在 Dart 这里,基于 fish_serializable 同样做了一些定制处理,在生成的 Model 里提供 toJson 和 fromJson 方法等,保证各种类型数据,包括 Map 和 List 等内包泛型类,能够很方便地进行转换。

监控方案设计

每个监控方案都有其业务场景的局限性,在目前阶段,主要考虑逻辑一致性。worker 内单次的逻辑闭环类似 tcp 握手和挥手的过程,应用内的数据流转类似消息队列,其传递过程如图:


null


由此我们确定 workerMonitor 运行的流程图如下:


null

性能监控

在该模式下的主流监控方案,会根据时间切片来观察 发起方/接收方的队列数据情况,时间切片有两种方式,第一种是设置定时器,第二种是在每次有数据调用时处理。



另外上报的方式也分为实时上报和聚合上报。考虑到目前 worker 的使用场景有闲时和忙时的明显区分,并且端上的长驻的频繁的定时上报任务对 ui 绘制会有一定影响,最终采用每次数据调用时统计队列内数据,同时在每次调用后增加超时定时器,如果有下次调用则取消超时定时器。

指标

在线上监控指标建设方面,参考 rabbitmq 监控,先定义初期需要观测的指标。初期核心关注消息丢失的情况和消息时延长的情况。由此我们确定指标如下:

null


Exception 监控

参考 ui 引擎对 crash 的监控,会在入口函数处统一接受异常信息以及异常堆栈,然后统一上报处理。这里在闲鱼公众号 Flutter 高可用相关文章中有详细介绍。

可行性验证

最后实现完成,调用代码及对应的 Handler 示例如下:

•iOS 端:


null

•Android 端:

null

•Handler:

null

为了测试我们的方案能否达到上线标准,在会玩首页场景下做暴力测试来验证。对比正常 Native 代码和 worker 处理数据,测试多次并发访问/有序访问条件下 CPU、内存以及时延等表现。


通过多次对比试验,FlutterWorker 方案在常见和高压的请求场景下短期内存和 cpu 水位增量少于 30M,长期内存和 cpu 水位增量小于 5M,并且时延低于原有方案的 5%。


三端接入后,数据处理只需要投入一个人力就可供多端使用,大量减少了重复工作,提升了研发效能。

总结和展望

当前跨平台是移动开发的趋势之一,各个公司、团队各有建树,百家争鸣。究其根本目的都是想提升研发效率,降低维护成本。各个方案都各有自己的独特优势,应该理性分析团队和业务的现状,选择适合的方案。


Flutter Worker 从逻辑跨平台的视角切入,取得了一些不错的效果。不过我们目前只完成了小部分的工作,仍有很多未完善的地方,在未来主要会从下面几个方面继续深入研究:

  • MethodChannel 优化。数据通道的通信强依赖 MethodChannel,从目前测试结果来其性能表现可以 cover 目前的业务场景,但长远来看,通道会成为 worker 性能瓶颈。从 dart_native 库得到启发,以类型映射指针的方式来替代原生的通道是一条可行的路。

  • 单元测试。逻辑处理函数有明确的输入和输出,写单测的效率很高。而且快速迭代的产品,很多是在原有的逻辑基础上添加新的逻辑,写单测的性价比较高。

  • 前端容器支持。先行版本只支持了 iOS、Android 和 Flutter,对于 Weex 和 H5 前端页面并没有很好的支持,未来期望能够提供优雅的方式接入前端容器。


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

原文链接:Flutter Worker —— 闲鱼这样实现“逻辑跨平台”

2021-03-18 08:001784

评论

发布
暂无评论
发现更多内容

Vol.3 人工智能这么热,你必须知道一点儿!

pyfn2030

人工智能

AB 测试平台的设计与实现

伴鱼技术团队

架构 系统设计 后端 A/B

Vol.2 谷歌不只有搜索

pyfn2030

谷歌Google

那些会阻碍程序员成长的细节[1]

MavenTalker

程序员 职业规划

《程序员的数学》笔记

Rex

读书笔记

计算机的时间

伴鱼技术团队

分布式 服务器 技术交流

绝了!Dataway让Spring Boot不再需要Controller、Service、DAO、Mapper

哈库纳

StringBoot DataQL

无需代码!通过 Dataway 配置一个带有分页查询的接口

哈库纳

spring springboot Dataway Hasor

如何用一台电脑制作一部动画短片?

zhoo299

动画 CG

说到做到

Yukun

拖延症

Vol.5 Go初探,新手必看!

pyfn2030

编程语言 新手指南

艺术生,我劝你Mac

zhoo299

Mac CG 艺术

Dataway 配置数据接口时和前端进行参数对接

哈库纳

Spring Boot DataQL Dataway Hasor

码农远程办公指北

大伟

Anaconda与虚拟环境

halapano

Python virtualenv Anaconda

从 0 到 1 搭建技术中台之技术文化篇

伴鱼技术团队

企业文化 技术管理

完美兼容老项目!Dataway 4.1.6 返回结构的全面控制

哈库纳

spring Spring Boot Dataway Hasor

Dataway 整合 Swagger2,让 API 管理更顺畅

哈库纳

Spring Boot DataQL Dataway Hasor

原创 | 使用JUnit、AssertJ和Mockito编写单元测试和实践TDD (十)在项目中准备测试环境

编程道与术

Java 编程 软件测试 TDD 单元测试

自己常用的一些快捷键 windows10

halapano

Windows技巧

代码简洁之路 [持续更新]

hq

Java 大前端 编程习惯

使用SpreadJS 开发在线问卷系统,构筑CCP(云数据采集)平台

葡萄城技术团队

数据挖掘 大数据 SpreadJS CCP

Wi-Fi p2p & ap 共存

贾献华

wifi p2p ap

系统服务化构建-两方OAuth

图南日晟

微服务 软件工程 身份认证 架构设计

Gartner 【RPA市场竞争格局】:中国厂商首次进入国际视野

人称T客

ARTS-WEEK01

子路无倦

ARTS 打卡计划

【快点查查】微信小程序使用流程

tomatocc

免费领课的活动你错过了么?

池建强

极客时间

Dataway 4.1.5 以上版本升级指南

哈库纳

string StringBoot Dataway Hasor

Vol.4 了解一下渗透测试

pyfn2030

黑客 网络安全

Vol.6 几个数据库相关的词

pyfn2030

数据库 大数据 新手指南

Flutter Worker —— 闲鱼这样实现“逻辑跨平台”_架构_闲鱼技术_InfoQ精选文章