导读:业务架构要随着业务发展做相应的演进, 继而支撑业务的快速发展。本文主要通过介绍闲鱼从零发展到千万级 DAU 应用的不同阶段的业务特点、核心问题以及针对性的架构演进, 来阐述业务架构的演进思路与心得。
闲鱼业务背景
技术架构的演进跟业务形态都是强相关的, 闲鱼的市场本质以及用户特点如下描述:
闲鱼是一个高性价比的二手交易市场。相比新品市场, 二手市场的市场空间就是 ” 用户在付出相同成本条件下有可能获取到更高的物品价值”,典型的比如 ” 游戏卡带, 乐高 ” 等这些功能型的产品。同时, 闲置市场也有着特殊存在的成本 - 信任成本, 信任成本主要体现在: 大部分二手可能没有售后服务; 每个人对二手物品残值有着自己的主观评价。
扩大市场空间有两种方式,1. 降低新人成本 2. 提升匹配效率
闲鱼与手淘差异性:
- 闲鱼与手淘的卖家差异: 非专业的个人卖家, 利益驱动弱。
- 发布产品差异: 为保证市场供给, 只能坚持轻发布。
- 商品差异: 结构化信息少, 没有历史累计行为。
闲鱼与手淘在业务、团队结构的差异性导致架构上不同的关注点, 导致不同的演进路线。
架构演进 - 试错期
架构随着业务阶段不断演进, 每个阶段都有核心的问题
- 试错期业务核心问题: 业务不断探索适合的商业模式
- 架构核心关注点: 提升响应速度, 快速支持业务上线
- 架构核心原则: 以质量换取速度, 可以牺牲一点线上质量 (业务可接受范围) 来换取更快的响应速度
App 发版速度 (尤其是 IOS) 跟不上业务快速迭代的上线周期, 动态性是端面临的主要问题, 因此端上采用了 Hybrid 的架构:
- URL Router: 所有请求路由到一个 H5 的链接, 通过 URI Schema 重定向到真正页面, 如果对应的 native 没有开发出来, 就用 H5 版本来实现, 解决安卓与 IOS 不同步的问题。
- 开关中心: 通过开关控制页面路由, 页面入口是否开启, 分版本控制, 参数变更等改动。
- Poplayer: 无需发版的情况下在已有的 Native 界面上弹出 H5 的部署容器, 来满足运营随时创建活动并需要一个活动入口的需求。
架构演进 - 发展期
发展期业务与架构核心问题:
- 业务核心问题: 隐约看到商业模式, 需要加速验证, 扩大规模。
- 架构关注点: 提升效率(为了有机会去做更多事情, 非降低整体成本), 建更多能力验证业务方向
- 架构演进方向: 前后端的协议、工具的自动化
服务端通过 Mbaas(服务端提供基础的数据源 (商品、用户、搜索、互动), 让客户端 / 前端通过类 SQL 的描述一次性获取自己想要的数据, 后端不需要增加接口) 来实现活动、feeds 投放的自动化。将更多精力投入到本地化、个性化、数据能力 (与算法、推荐、搜索打通) 的建设中。
客户端开发关注两个点:
- 对外整体连接协议的梳理, 在容器这端演化成 Service Bus(类似服务端的 ESB),对具体的实现进行封装, 以方便后续基础能力的可替换。
- 组件库的建立, 新做一个页面的时候, 能通过现有的 UI 组件进行简单组装, 不需要重 0 开始搭建。组件与服务端打通, 组件组装逻辑与数据直接由服务端完成, 客户端负责解析与渲染。
因此这个时期客户端更多的工作是支持交互的基础的 UI 组件和动态适配性。
架构演进 - 平台期
随着业务的发展, 闲鱼基于商品体系的业务达到十几种, 逐渐向平台期发展。平台期业务与架构核心问题:
- 业务核心问题: 需要让更多的二方、三方参与到共享经济平台的建设中, 但是平台生态建设又超出了闲鱼自身的能力
- 架构核心关注点: 扩展性(具备接入业务的能力)、业务隔离(已接入业务平稳运行)、平台基础能力建设(业务更好的发展)
- 架构原则: 做一些更基础的规划, 然后把更多的可能性、动态性留给二方或者三方完成
业务隔离框架 Swak
核心解决因业务发展带来的代码耦合问题, 问题主要体现在整体开发、运维效率低,稳定性差。核心思路是分离系统中不可变和可变的部分; 分离出”做什么”与”怎么做”、“谁去做”。
将业务中不变的部分放入主干, 定义出做什么; 变化的部分以扩展点形式开放出来, 让具体的业务放自己来实现, 完成怎么做,谁去做。Swak 的扩展点实现支持远程调用, 可以让业务实现应用级别的隔离 , 相比传统的分包、分模块隔离方式更加彻底。
当前, 闲鱼商品主链路完成基于 Swak 的升级。下面是一个闲鱼币个性化业务的代码案例:
平台通用能力
平台必须提供一些通用能力更好的支持业务发展:
- 实时选品投放能力 – 马赫:解决因闲鱼商品特性 (结构化信息少, 新品成交占比高) 导致传统离线选品转换率差的问题。
- 实时线上故障定位能力 – 神探: 解决类闲鱼规模系统因依赖多、场景多, 导致线上问题频发、问题定位投入成本高的问题。核心思路是对系统每一次错误的请求链路进行实时采集、分析、聚合再可视化展现, 将整体故障定位过程变成自动化。
架构演进 - 云端一体化
云端一体化 – 背景
随着无线发展, 移动研发逐渐向多端化发展(IOT、小程序)。传统的基于 Native+Web+服务端的开发方式,逐渐出现瓶颈,我们会发现例如:
- 端上同学离业务越来越远,服务端同学没时间做底层领域沉淀。
- 各端研发之间存在大量的协同, 整体研发效率低下。
- 招人也难了, 需要同时招多个技术栈的同学
在这种背景下, 我们的关注点回到 研发效率 上, 从整体研发架构、研发模式出发, 思考什么样的架构演进、关系重塑才能适合当前的业务形态。我们希望探索出 适合“闲鱼这样规模的具有独立 APP”的高效研发架构, 形成云端一体化的研发能力,支持一云多端的发展。
云端一体化 – 演进步骤
朝着云端一体化的方向, 架构的升级大概分成 3 个步骤:
- 端上用 Flutter 实现了两端 (IOS、Android) 统一。无线发展了现在, 跨平台的需求已经非常强烈, 团队招聘需要考虑 Android,IOS 配比、一个业务需要在两端都写一次, 考虑双端逻辑一致、测试要测两遍。所以跨平台的方案能非常直接有效的降低研发成本, 解决资源均衡的问题。
- Flutter+dart 实现了三端 (IOS、Android、服务端) 技术栈统一。端上统一了,再通过云端技术栈的打通来减少云端的协同。参考前端+Node.js 的方案 , 闲鱼服务端用 dart(Flutter 也是 dart 语言)替换 Java, 作为服务端 server 的语言。
- Flutter+ Faas(dart runtime)+Nexus。技术栈统一了, 人员还不能互补, 最新闲鱼将 Dart 容器嵌入到 Faas 容器中, 配合跨云端的一体化业务研发框架 Nexus, 进行了一体化的研发模式的探索, 使得一个研发人员能从端到服务端完成整个业务的闭环。
云端一体化 – 跨端方案选择
架构方案的选择, 可能造成巨大并且长远的影响。在架构的演进中, 我们要善于定义问题, 然后通过不断迭代来解决问题, 最后才能形成适合自己业务特性的架构。
闲鱼也是一样,所谓没有银弹的解决方案, 在跨平台方案的选型中, 充分对比了 Flutter 与 RN 的差异性, 优缺点。
闲鱼认为 ” 跨平台与高性能是我们当前的核心诉求”, 再结合团队内 native 技术栈的同学较多这个因素, 我们最终选择了 Flutter 作为跨端解决方案。
云端一体化 – 云端协同
Flutter 两端统一后, 会发现客户端与服务端虽然都在做同一个业务, 不仅技术栈没有统一, 而且存在着大量协同的工作, 同时端、云的同学仍然无法真正互补和一体化打通。
因此, 我们开始思考是否能有一体的架构 , 能让一个同学可以 Cover 一个云到端的完整业务,形成业务闭环。
这不仅仅是效率的提升, 更能为业务开发同学带来更大的成长空间,可以完整的和专注的思考业务。
云端一体化 – 关键问题以及解法
我们梳理了需要解决的关键问题:
- 如何消除云端技术壁垒?首先要统一技术栈,其次端同学对云的思维模式、知识储备上的差异,需要有办法消除。
- 如何使工作总量减少 (1+1<2)?一体化下需要使总工作量降低, 不是简单的进行工作量转移。
- 如何促进生产关系重塑?生产力发生变化, 需要建立新的生产关系。
面向这些问题,闲鱼的解法思路:
- 统一技术栈: Dart 具备服务端语言特点, 强类型, 支持异步与并发, 甚至更快的启动速度,因此作为服务端的 server 完全没有问题。Dart 落地过程中更多的解决的是生态的问题(阿里的大部分生态都是基于 java 来建设的, 例如中间件、消息、远程调用)。我们主要通过通过 C ++ 扩展、SideCar 方式做桥接,Service Mesh 来解决。
- 云端差异抹平: 通过 Faas , Baas 等无服务器能力的建设, 抹平除写代码外的其他差异性 (运维、故障定位等), 使得客户端同学能写服务端; 通过 UI2Code(根据图片生成 UI 代码), 页面代码模板化(页面容器,数据管理) 使得服务端写客户端
- 一体化总体效率提升: 以往的架构是云、端分开架构的,一体化后下沉跨云端的研发框架 Nexus,通过框架、工程体系的支持, 消除协议层, 重新定义 UI 与逻辑分层, 带来了总工作量 1+1<2
- 关系重塑: 领域下沉能让原来服务端同学更加专注领域建设, 使领域层更加稳定, 让业务层与领域层的变化比例, 从当前的 2:1, 提高到 5:1 甚至更高。让大家的关注点都集中在自己的范围内。
云端一体化 – 业务落地
目前一体化的研发模式已经在闲鱼多个场景落地, 我们以下单页的改造举例:
改造前: 下单页有着复杂的 渲染 交互逻辑, 之前大部分逻辑都是在端上。需要两个客户端 + 一个服务端的同学来维护。
改造后:
- 将客户端界面从 IOS、Android 两端统一成了 Flutter, 后续只需要一个同学维护即可, 也不会出现逻辑不一致的情况。
- 原来云端分离的业务逻辑全部下沉到了 Faas(Dart), 将原来分散在端与服务端的逻辑进行归一, 有机会做更多的规划建设, 同时也是端的同一个同学来维护。
- Faas 层调用底层领域服务来完成自己的业务,原来服务端的同学更多投入到交易能力的建设上。
框架下沉:
跨云端业务研发框架 Nexus: 寓意着能将客户端与服务端连接在一起。
核心思想:将 UI 与逻辑分离, 框架限定了端上只负责 UI 与状态的存储, 所有的逻辑都在 Faas 中完成。
非常适合类似下单页的领域稳定的的场景。
云端一体化 – 收益
云端一体化能在多个方面给我们带来收益, 包括 团队人员资源的均衡、协同效率的提升、业务的一致性以及人员的新的成长空间 。
特别适合类似闲鱼规模的具有独立 app 的研发团队
小结
本文分别介绍了闲鱼从快速试错期、发展期、平台期、云端一体化的整体架构演进以及过程中的思考。对核心问题的定义, 以及做的具体演进。
我们会发现,架构的演化总是优于一步到位, 没有一个大而全或者特效的方法可以一直提升系统效率。软件工程是一个超级复杂的系统, 尤其是业务架构, 需要随着业务随时变化。明确当前业务特点和核心问题才是设计的根本,不符合业务的架构再领先也没用。相信所有架构师都有这样的体会。
希望通过以上的分享对大家有所启发!
阿里云双 11 亿元补贴提前领,进入抽取 iPhone 11 Pro:https://www.aliyun.com/1111/2…
本文作者:闲鱼技术 - 扬羽
阅读原文
本文为云栖社区原创内容,未经允许不得转载。