路由器后端页⾯⽤什么语⾔开发的_Nexus协议,闲鱼⼀体化 开发的幕后玩家
Serverless是这⼏年兴起的⼀个概念,Serverless可以帮助开发者减轻甚⾄摆脱传统后端应⽤开发所需要的服务器设备的设置和运维⼯作,并以服务接⼝的⽅式为开发者提供所需要的功能。它希望开发者更加专注于应⽤逻辑本⾝,⽽不是被琐碎的基础设施细节所”“。
⽽FaaS是Serverless的⼀种⽐较好的实践⽅式。⾃从亚马逊的AWS在14年推出Lambada之后,FaaS这种后端发开⽅式迅速被⼤家接受并应⽤。它拥有更加轻量、事件驱动的特点。
割管刀
超薄继电器闲鱼选择使⽤Flutter + FaaS体系来实现云端⼀体化的开发模式也正是看中了Flutter和FaaS技术本⾝都是轻量的、⾯向应⽤的技术。与⼀体化本⾝希望开发者尽可能关注整体的业务逻辑⾮常契合。
Flutter + FaaS的云端⼀体化开发模式已经在闲鱼中被使⽤了⼀段时间。同事们之前也有过⼀些⽂章来介绍⼀体化开发在闲鱼演进和落地的过程。在这些⽂章中,都提到了Logic_engine、Nexus_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 change的Action,带上页⾯所需要的所有state数据,就可以达到效果。现实场景中,某些页⾯的state数据可能巨⼤⽆⽐,不好直接传输。我们做了⼀个JsonPatch库来解决这种场景下的问题,如果FaaS只修改了state中的⼀部分数据,则可以通过下发patch的⽅式由端来合成⼀个新的、完整的state。
对于副作⽤处理的部分,⼤部分的副作⽤都来⾃于⽐如Dialog,页⾯跳转等。这类操作是通⽤的,有共性的,我们同样使⽤⼀类叫做native api的Action来描述,这些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,变得更加⼀体化。作者:海潴
本⽂为阿⾥云原创内容,未经允许不得转载。