Nexus协议,闲鱼一体化开发的幕后玩家

本文涉及的产品
函数计算FC,每月15万CU 3个月
简介: 手牵手,一起走

作者:海潴

Serverless是这几年兴起的一个概念,Serverless可以帮助开发者减轻甚至摆脱传统后端应用开发所需要的服务器设备的设置和运维工作,并以服务接口的方式为开发者提供所需要的功能。它希望开发者更加专注于应用逻辑本身,而不是被琐碎的基础设施细节所”绑架“。

而FaaS是Serverless的一种比较好的实践方式。自从亚马逊的AWS在14年推出Lambada之后,FaaS这种后端发开方式迅速被大家接受并应用。它拥有更加轻量、事件驱动的特点。

闲鱼选择使用Flutter + FaaS体系来实现云端一体化的开发模式也正是看中了Flutter和FaaS技术本身都是轻量的、面向应用的技术。与一体化本身希望开发者尽可能关注整体的业务逻辑非常契合。

Flutter + FaaS的云端一体化开发模式已经在闲鱼中被使用了一段时间。同事们之前也有过一些文章来介绍一体化开发在闲鱼演进和落地的过程。在这些文章中,都提到了Logic_engineNexus_Framework等字眼。它们一直默默得在业务开发同学的身后,支撑着一体化的落地和发展。

今天,我们就来介绍一下这个一体化的幕后推手--- Nexus协议,以及基于它衍生出来的框架和库。

Nexus协议的由来

一开始说要做Flutter + FaaS一体化开发的时候,我们对”一体化“这三个字的认知相对比较模糊,只是知道端侧的同学可以用Dart这门语言来写FaaS函数,这样的语言上的一体化。对于FaaS所能做的事,也仅仅停留在前端实施已久的BFF层面。那个阶段,对于要做些什么,还是比较迷茫的。

阿里的同学经常说:

你不知道能做些什么,是因为想得还不够清楚

本着这样的想法,一体化小组经常聚在一起讨(liao)论(tian),不管Flutter + FaaS有没有一体化,反正我们小组先”一体化“了再说。

整个一体化的概念在讨论中慢慢变得清晰,首现我们对于一体化进行了定义,它应该是这样的一个形态:

  1. 语言一体化
  2. 开发模式与架构一体化

最终达到开发Flutter页面和开发FaaS无明显gap,像在开发一整个应用的体验。

语言一体化

由于Flutter本身是以Dart作为开发语言,那么我们自然也选择它作为FaaS的开发语言。闲鱼在之前已经实践过了Dart Server这种开发方式,在Dart runtime、相关开发工具方面有非常深厚的沉淀。组内的同学将这个runtime经过修改之后移植到了集团的FaaS平台Gaia上。

开发同学不仅可以在端上使用hotreload进行页面快速调试,同样可以使用这项功能在FaaS平台上快速部署与调试,极大得提升了部署和调试的体验。

开发模式与架构一体化

在语言一体化的基础上,我们同样希望开发者在开发Flutter页面和FaaS函数的时候,有着相同的心智。

在传统的前后端分离开发模式中,端侧的开发与后端开发有着比较明显的不同,端侧通过和后端约定数据结构的方式获取用于页面渲染和处理用户输入的数据。这种模式下,双方仅对数据进行了依赖,各自属于不同的系统。

在一体化的模式下,我们希望开发者能把端侧页面和FaaS函数当成同一个系统来看待。它们应该是一个有机的整体,共同完成一个页面的功能。在职责上,端侧代码主要处理UI的渲染,FaaS函数主要处理逻辑与副作用。

开发者应该可以像在一个系统内一样进行相互的调用,就好像你在本地调用一个对象的函数那样自然。

但显然,端与FaaS现实中还是属于两个系统的,如何能够做到像调用函数一样自然呢?它们之间又以什么样方式进行触发呢?

事件驱动

在常见的客户端页面开发过程中,端侧逻辑总是围绕着三个操作在进行,不管代码多少,写成什么样,这些逻辑代码最终都会产生:

  1. 发起一个网络请求(remote req)
  2. 调用一个公共函数(native api)
  3. 修改页面数据并渲染(state change)

这样的三个效果。

比如页面的初始化过程,就是典型的 remote req=>state change=>render的过程。

当然这是精简之后的流程,由于一个http请求回来后的数据并不能直接作用于页面state,通常还需要先对数据进行一下处理。

这些动作都会由一个明显的事件来触发,通常来说是用户进行的交互事件,不论是请求、页面渲染,或者弹出一个Dialog,进行一次页面间的跳转,它们都不会自发得进行(否则看上去有些诡异)。

而一个端上的事件,也可能会传导到FaaS上,来驱动FaaS上的逻辑函数对这个事件进行处理。当我们把端和FaaS看成一个整体的时候,这个事件就是在一个系统中流转。

于是我们总结出了第一张图:

逻辑归一与互相调用

在传统的开发模型下,页面逻辑、状态、展示三者之间的流转是在端侧进行的,后端负责了一部分的逻辑处理(通常这部分逻辑是需要对于各种领域接口进行调用)。

而还有一部分领域数据到UI state的一些转换逻辑,则是端、后端都会做一部分。这两部分逻辑分散在两端,通过某种弱的协议进行连接。

引入了FaaS之后,自然可以把逻辑放到FaaS上实现,那么请求回来的数据理论上可以直接作用于页面渲染。

如果我们再进一步,不如直接让FaaS来指挥端上的UI怎么做好了。就好像FaaS是一个导演,而端侧UI是一个提线木偶,FaaS怎么说,UI怎么变。这样把业务相关的逻辑都搬上FaaS去,端侧专注于如何将state渲染到UI上,两个部分组合成为一个页面整体,岂不是更加一体化?

于是我们有了第二张图:

逻辑归一到FaaS之后,FaaS已经可以跳过传统的弱协议,直面端侧页面了。对于后端来说,一个请求可以映射到一个具体的处理函数。我们可以不太严谨得说,一直以来,客户端是有调用后端函数的能力的。那么既然我们现在想让FaaS来指挥端上的UI的变化,势必也要让FaaS具有调用端侧函数的能力。

我们把一次调用抽象为一个Action,每一个Action的背后都有一个特定的函数为它提供真实的逻辑,也就是说,一个特定的Action,可以用来描述一个特定的函数与函数背后的逻辑代码,Action本身就是一个函数签名。

那么端侧需要提供多少函数给FaaS呢?当逻辑归一到FaaS上之后,我们会发现端侧的大部分实现都围绕着两部分进行:

  1. UI展现
  2. 副作用处理

UI的展现是”纯“的,它基本上都可以由一个页面的state数据来描述,也就是说,大部分情况下,一个state就描述当前UI的状态。那么对于端侧来说,只需要提供一个state到UI的映射函数,理论上就可以让FaaS具有更新端侧UI的能力。也就是说,假设FaaS函数想要更新页面,只需要下发一个state changeAction,带上页面所需要的所有state数据,就可以达到效果。现实场景中,某些页面的state数据可能巨大无比,不好直接传输。我们做了一个JsonPatch库来解决这种场景下的问题,如果FaaS只修改了state中的一部分数据,则可以通过下发patch的方式由端来合成一个新的、完整的state。

对于副作用处理的部分,大部分的副作用都来自于比如Dialog,页面跳转等。这类操作是通用的,有共性的,我们同样使用一类叫做native apiAction来描述,这些Action与它们背后的处理函数,将面向所有使用了Nexus协议的页面提供这样的能力。

这两类函数的抽象,已经可以cover 80%的页面需求了,而剩下的20%复杂交互的页面,我们提供custom类型的Action来让开发者进行自定义。

总结

通过对于一体化的定义,以及拆分了需要的功能之后,Nexus协议就破土而出了。它是一个

基于Action的,提供Client/FaaS系统间调用的协议

Action的调度者-LogicEngine

我们有了可以用于两个系统间进行相互调用的协议,相当于我们有了一门语言,这门语言只有我们自己认识,所以还需要一个解释器来执行它。

LogiceEngine就是这样的一个执行器。

如果我们给它下一个定义,LogicEngine就是一个:

基于Nexus的Action协议的,提供Client、FaaS之间相互调用能力的库

Engine本身不提供任何具体的逻辑能力,所有的逻辑能力都需要通过函数的形式注册到Engine中,并绑定到一个具体类型的Action上去。

所以Engine的设计相对明确:

  1. 对外,它提供函数注册和基于消息(action)执行函数调用功能
  2. 对内,进行消息解析、函数匹配和执行上下文管理

开发者通过post函数来发出一个Action,相当于通过Engine调用了一个函数,这个函数可能在本地,也可能在FaaS上。这并不是开发者需要关心的内容。甚至于,这个调用会产生什么影响,也不是当前调用者所需要关心的。

因为调用的发起者实际只是发出了自己的一个意图,比如在实践中,我们会在用户按下"下单"按钮的时候提交一个意图(Action)。

这个意图最终会产生什么样的UI变化,FaaS会通过一个state change或者native api形式的Action直接调用到具体的实现函数去。

而端侧注册在Engine的函数不会很多,前面有提到过,大部分UI编程中的逻辑,都可以被归纳为三类。所以我们大多数时候只需要注册三种固定类型的处理函数就可以了。

展望

有了Nexus协议、三类通用处理函数的抽象和LogicEngine,意图=>作用中间过程就可以变得透明。

但这些远远不够,

后续我们还希望对协议进行升级,从现有的json提升到一个更加类型安全的协议上。
我们也希望有一个IDL工具,可以自动得将面向Action调用转换成面向接口调用,让开发者有更好的调用体验。
我们还希望改变现有单向的请求=>应答模型,让FaaS可以自由得调用端侧函数,再次突破两个系统之间的gap,变得更加一体化。

相关实践学习
【文生图】一键部署Stable Diffusion基于函数计算
本实验教你如何在函数计算FC上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。函数计算提供一定的免费额度供用户使用。本实验答疑钉钉群:29290019867
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
相关文章
|
16天前
|
图形学 iOS开发 Android开发
从Unity开发到移动平台制胜攻略:全面解析iOS与Android应用发布流程,助你轻松掌握跨平台发布技巧,打造爆款手游不是梦——性能优化、广告集成与内购设置全包含
【8月更文挑战第31天】本书详细介绍了如何在Unity中设置项目以适应移动设备,涵盖性能优化、集成广告及内购功能等关键步骤。通过具体示例和代码片段,指导读者完成iOS和Android应用的打包与发布,确保应用顺利上线并获得成功。无论是性能调整还是平台特定的操作,本书均提供了全面的解决方案。
68 0
游戏直播软件源码开发搭建,平台获利方法有哪些?
在互联网新时代,随着直播技术成熟,泛娱乐产业备受市场追捧,当中娱乐游戏直播平台在这一行业中处于核心关注热点。即使由于短视频的兴起,其增长速度显著下降,但是其吸金实力始终不可小嘘。
|
前端开发 JavaScript
Primordial Farm(初元农场)星球生态游戏开发源代码部署流程
Primordial Farm(初元农场)星球生态游戏开发源代码部署流程
|
区块链 数据安全/隐私保护 开发者
魔豹联盟佛萨奇2.0矩阵模式系统开发玩法介绍代码部署
魔豹联盟佛萨奇2.0矩阵模式系统开发玩法介绍代码部署
183 0
|
Web App开发 安全 架构师
网易云信开源会议和低延时直播两大项目:对开发者完全开放、支持修改后商用
“我始终相信开源会产生裂变。当越来越多的开发者参与到开源项目中,这套代码、组件就不仅仅只是一套代码,它会变成我们未来的生产力和竞争力。”网易智企低延时直播开源负责人、网易云信流媒体首席架构师吴桐说道。
220 0
网易云信开源会议和低延时直播两大项目:对开发者完全开放、支持修改后商用
|
运维 监控 安全
无接触,云办公!5天完成手机淘宝新版本迭代,揭秘阿里工程师协同研发“神器”
5天完成手机淘宝新版本迭代,阿里工程师用“神器”刷新纪录
1198 0
|
新零售 中间件 Java
阿里中间件(Aliware)一大波优质JD在向你靠近!
这是一个神奇的团队,在技术部门竟然有各种风格的小姐姐? 这是一个较真的团队,对业务、技术的声音没有功利没有对错,只有自由讨论。 这是一个有理想的团队,他们要把从阿里孵化出来的中间件技术赋能给全社会。 想要一探究竟?欢迎你的加入~!
|
前端开发 JavaScript 定位技术
阿里自主研发的互动游戏引擎Hilo开源啦!【内有详解】
Hilo,一套HTML5跨终端的互动游戏解决方案开源啦!。Hilo支持了多届淘宝&天猫狂欢城等双十一大型和日常营销活动。内核极简,提供包括DOM,Canvas,Flash,WebGL等多种渲染方案,满足全终端和性能要求。详细介绍见内文。
42242 0
|
搜索推荐 开发者
基于微信生态的小程序如何创造连接?
互联网的本质是连接,谁创造了连接,谁就掌握的互联网的本质,谁就掌握了互联网源泉。 从“移动互联网”到“微信互联网”   自从2018年3月份微信上线小程序游戏,从来没有一个产品能够这样一个快速的覆盖能力,迅猛的扩展到每个人身边。
879 0