闲鱼基于Dart生态的FaaS前端一体化建设
背景
随着Flutter对现有业务的不断参透,闲鱼Serverless基建的重心也倾向了dart生态,先是将dart容器打包到服务器上,实现dart编程语言的统一,在统一的容器之上实现编程框架一体化(nexus、story),以及后端领域服务一体化。基于dart生态下,前端的FaaS在研发交付其实并不高效,研发阶段主要面临的问题是:
编程语言不统一:编程语言本身虽然不是最大的障碍,但这也确实给前端开发者增加不少门槛,而且更重要的是语言背后的生态、环境与体系更是一道高高的墙。
工程割裂与背后环境复杂:端侧一个工程,FaaS侧也有一个独立的工程,它们背后都有着自己的一套构建、调试、集成/发布的工具链;除此之外FaaS还有自己配套的环境、runtime、框架作为支撑。开发者面对这样复杂的FaaS研发环境与双重的研发工作流是无法做到高效交付的。
编程语言一体化
Typescript作为Javascript的超集,弥补了Javascript的静态类型检查,同时扩展了很多OOP的语法特性,使得TS跟dart在语法特性上有非常多相似的地方,为后面的转换提供了可能与便利。要实现语言层面转换背后都会有一个小型的编译器在支撑着,不过幸运的是Typescript官方已经提供语法解析器,通过它我们很容易就拿到一份可靠的AST,所以我们只需要实现一个dart generator就行了。生成器大致可以分为四个层面的工作:
基础语法转换
原生方法差异转换
业务框架桥接
依赖库与头文件桥接
基础语法转换
这部分很好理解,就是最基本的语法层面转换,用个最简单的例子看下。
原生方法差异转换
两种语言在内置原生方法上也有很大区别,举个例子:可以看到下面数组的实例方法在两种语言体系上是不一致的,除了数组插入还有很多很多原生方法是不一致的。当然也没太必要被这个难以想象的数量吓到,大多数情况:90%的场景只会用到那10%的方法,完成了10%的转换就能cover到90%的场景。
// ts
list2.push(10)
// dart
list2.add(10)
要实现系统方法的差异转化首先要识别出该方法是来自于哪个类,比如说 list2.push(10)
我不可能只检查 push
,因为随便一个类/对象都可以实现一个push方法。我们必须识别出 list2.push
的 push
属于 Array.push
,别忘了整个typescript编译器中占比最大的类型检查器 ts.TypeChecker
,它可以很好的帮我们解决这个问题。大致思路如下:
业务框架桥接
在完成上面两块能力转换后,常规裸写一段逻辑进行转换问题是不大的;但业务是不可能裸写,业务需要框架,需要借助框架进行通讯、与容器打交道。需要借助框架进行业务抽象,更好的组织、管理业务逻辑。我们来看个例子:
DartMtopResult<String> result = awaitHsfServices.request(moduleName, parameter);
上面的这段代码是用于在dart侧进行内部服务请求的,从代码表明我们可以获取到三部分信息:
有一个HsfServices的类
HsfServices有一个同步返回结果的request方法,接收两个参数
最终返回DartMtopResult的数据结构
我们再翻一下 request
的实现与 DartMtopResult
的申明:
// DartMtopResult.dart
classDartMtopResult<T> implements xxxx {T data;
bool success;
String errMsg;
String errCode;
// more code hidden
}
// HsfServices.dart
classHsfServices{
// more code hidden
staticFuture<DartMtopResult<String>> request(String moduletName, String parameter) async{
// more code hidden
}
// more code hidden
}
就看这么多足够了,打个比方如果我希望在typescript侧编写一个能用 HsfServices.request
发请求的ts代码且不报错,那应该怎么做呢?像下面这样申明一个:
// HsfServices.d.ts
export declare classHsfServices{
static request(moduletName: string, parameter: string): Promise<DartMtopResult<string>>;
}
// DartMtopResult.d.ts
export declare classDartMtopResult<T> {data: T;success: boolean;errMsg: string;errCode: string;
}
// business.ts
import{HsfServices} from"HsfServices.d.ts"
import{DartMtopResult} from"DartMtopResult.d.ts"
const result: DartMtopResult<string>= awaitHsfServices.request<DartMtopResult<string>>('recycleGet', parameter);
非常简单就能让业务逻辑正常写下去并且不报错。但你肯定会说这样的代码也没法运行起来,是的,但我并不需要上面代码运行起来,我需要的是将它转成dart,并能在dart runtime中运行就可以了。大致的桥接思路如下:
依赖库与头文件桥接
这部分工作是从业务框架桥接中衍生出来的,我们还是用一个例子来说明一下问题产生的原因。
ts源码如下:
// business.ts
import {HsfServices} from "@ali/faas-hsf"
import {DartMtopResult} from "@ali/faas-mtop-result"
const result: DartMtopResult<string> = await HsfServices.request<DartMtopResult<string>>('recycleGet', parameter);
dart源码如下:
// business.dart
import 'package:hsf_services/hsf_services.dart';
import 'package:dart_mtop_result/dart_mtop_result.dart';
DartMtopResult<String> result = await HsfServices.request(moduleName, parameter);
可以看到上面逻辑除了发请求部分要转成dart,还有业务引用头文件需要桥接过去,而头文件的引入通常是靠pub依赖包(pubspec.yaml)安装进来的,就意味着转换器需要拿到 @ali/faas-hsf
对应dart侧的pub包与引入头文件。我们的解决思路大致是这样的:在 @ali/faas-hsf
模块中放入 faas.yaml
文件来指定对应的映射关系。
@ali/faas-hsf
|--lib/
|--faas.yaml
|--package.json
// faas.yaml
faas_pub:# 映射的dart侧依赖包hsf_services: ^1.1.7# 映射引入头文件index: hsf_services.dart
研发过程中再通过工程脚手架来自动完成这之间的映射关系的提取:头文件映射与依赖包映射。头文件映射最终会交给转换器,而依赖包映射会交给背后自动维护着的dart工程(后面会提到背后自动维护的dart工程)。大概的思路如下图所示:
研发工程一体化
编程语言一体化只是整个FaaS一体化研发的第一步,也只有统一了编程语言之后,背后的生态(npm)、工具链(build)与工程才可能一体化。我们看下现状:开发者面对的是两个割裂的工程,两套不同的环境、生态。这正如文章一开始所说的:编程语言本身不是最大的障碍,但语言背后的环境与生态却是一道高高的墙。在我们统一编程语言之后,研发工程一体化就变得可行了。
正如上图所示,FaaS工程本身的复杂在于整个工程需要运行在一个本地容器之中,因为容器要为工程提供runtime、相应的工具链、框架依赖等能力。所以本地容器本身是必不可少的,我们能做的只是尽可能让开发者无感容器的存在;除此之外还要对两个工程的逻辑做一定的融合,大致可以抽象成四部分工作:
研发代码层面融合
代码层面融合包括两部分:业务逻辑融合、业务逻辑所依赖编程框架融合。分别体现在 faas_src
存放业务逻辑的ts版, package.json
存放业务逻辑所依赖的编程框架(前面我们介绍到业务框架桥接最终就体现在端侧的依赖包上)
├── faas_pub.yaml
├── faas_src
│ └── Home
│ └── index.ts
├── package.json
├── src
│ ├── components
│ └── pages
│ └── Home
│ ├── index.css
│ └── index.js
└── README.md
FaaS侧的工程黑盒化
使端侧脚手架全权接管FaaS侧的工程初始化、热部署、调试信息,暴露出来给开发者的只有一套工具链,只有两个指令 init
dev
,让开发者0门槛初始化出一套统一而可靠环境的FaaS工程。
对接编译器进行研发实时编译
这部分主要负责对接转换器实时将ts编译成dart,并同步到黑盒中的FaaS工程。在实时编译过程有两部分内容:一部分是纯ts逻辑编译成dart,另一部分是依赖包的同步安装,其中 faas_pub.yaml
由脚手架通过探测端侧package.json中的faas依赖包来进行提取生成的,并不需要人工维护。
串联调试阶段的编译流
从保存每一个改动到在浏览器上能成功发起一个faas函数请求,这之间大致经过这些步骤:监控改动、编译代码、产物部署的流,由统一的端侧脚手架进行串联起来。
效果
经过编程语言的一体化后,我们不仅为开发者提供一种熟悉的技术栈,也为后面工程一体化提供了可能性;再经过工程一体化后,我们为开发者解决了工程割裂,解决背后复杂的FaaS本地运行环境,带来与原研发模式基本一致的研发体验。
后续
一体化之路还很多要去建设的,调试、发布、回滚等等;除此之外,FaaS毕竟还是运行在后端,最终通过网络协议与端侧通讯,那在两份代码中必然存在两份数据结构申明,两套封包解包逻辑;这为后面数据结构的一体化与自动化建设提供了很好的发挥余地。
闲鱼技术团队不仅是阿里巴巴集团旗下闲置交易社区的创造者,更是移动与高并发大数据应用新技术的引导者与创新者。我们与Google Flutter/Dart小组密切合作,为社区贡献了多个高star的项目和大量PR。我们正在积极探索深度学习和视觉技术在互动、交易、社区场景的创新应用。闲鱼技术与集团中间件团队共同打造的FaaS平台每天支持数以千万级用户的高并发访问场景。
就是现在!客户端/服务端java/架构/前端/质量工程师面向社会+校园招聘,base杭州阿里巴巴西溪园区,一起做有创想空间的社区产品、做深度顶级的开源项目,一起拓展技术边界成就极致!
*投喂简历给小闲鱼→guicai.gxy@alibaba-inc.com
开源项目、峰会直击、关键洞察、深度解读
请认准闲鱼技术
闲鱼基于Dart生态的FaaS前端一体化建设相关推荐
- dart js转换_基于dart生态的FaaS前端一体化建设
作者:闲鱼技术-羲凡 背景 随着Flutter对现有业务的不断参透,闲鱼Serverless基建的重心也倾向了dart生态,先是将dart容器打包到服务器上,实现dart编程语言的统一,在统一的容器之 ...
- GMTC2019|闲鱼-基于Flutter的架构演进与创新
2012年应届毕业加入阿里巴巴,主导了闲鱼基于Flutter的新混合架构,同时推进了Flutter在闲鱼各业务线的落地.未来将持续关注终端技术的演变及趋势 Flutter的优势与挑战 Flutter是 ...
- 闲鱼基于 Flutter 的移动端跨平台应用实践
闲鱼为什么使用 Flutter Flutter 作为 Google 新一代的跨平台框架,有较多的优点,但跟其他跨平台解决方案相比,最吸引我们的是它的高性能,可以轻松构建更流畅的 UI.虽然各跨平台方案 ...
- 闲鱼代码Java_面向未来的黑科技——UI2CODE闲鱼基于图片生成跨端代码
作者:闲鱼技术-青页 一直以来, 如何从'视觉稿'精确的还原出 对应的UI侧代码 一直是端侧开发同学工作里消耗比较大的部分,一方面这部分的工作 比较确定缺少技术深度,另一方面视觉设计师也需要投入大量的 ...
- 闲鱼靠什么支撑起万亿的交易规模?| 云原生Talk
造梦者 | 王树彬,阿里巴巴闲鱼架构负责人 2014年6月28日,阿里即将赴美上市的这一年,西溪园区的一个茶水间里,28个人日夜赶工了三个月后,上线了一个闲置交易平台--闲鱼.今年5月份,在阿里巴巴的 ...
- 闲鱼的云原生故事:靠什么支撑起万亿的交易规模?
来源 | 阿里巴巴中间件 作者 | 王树彬,阿里巴巴闲鱼架构负责人 责编 | Carol 2014年6月28日,阿里即将赴美上市的这一年,西溪园区的一个茶水间里,28个人日夜赶工了三个月后,上线了一个 ...
- 阿里巴巴闲鱼架构负责人王树彬:万亿交易规模技术架构实践
中生代技术 链接技术大咖,分享技术干货 全文:5000字 预见未来的最好方式就是创造未来,用「云原生Talk」记录云原生时代下每个造梦者的故事. 造梦者 | 王树彬,阿里巴巴闲鱼架构负责人 2014年 ...
- 闲鱼靠什么支撑起万亿的交易规模?
作者 | 禾易 来源 | 阿里巴巴中间件(ID:Aliware_2018) 造梦者 | 王树彬,阿里巴巴闲鱼架构负责人 2014年6月28日,阿里即将赴美上市的这一年,西溪园区的一个茶水间里,28个人 ...
- 分享 | 闲鱼靠什么支撑起万亿的交易规模?
点击上方 IT牧场 ,选择 置顶或者星标 技术干货每日送达! 造梦者 | 王树彬,阿里巴巴闲鱼架构负责人 2014年6月28日,阿里即将赴美上市的这一年,西溪园区的一个茶水间里,28个人日夜赶工了三个 ...
最新文章
- 慢动作频闪怎么解决_Vlog的视频解决方案——索尼A6400
- Linux--VI命令大全
- 2008_10_28_星期二
- 【资源】《动手学数据分析》开源教程完整发布!
- self-在类的外部给对象增加属性
- MyStringUtil.java String工具类
- C++学习_第1章_从C到C++
- dd 转换和拷贝复制文件
- HBuilderX安装教程
- 2022年的1024程序员节有啥好玩的小游戏推荐?
- 【laravel5.7】第一个Laravel接口之中央气象台天气接口
- 中国大数据论坛第八期教育成都沙龙成功
- AI仿生:人类进化新可能
- 中国App增长联盟,和优秀的创始人玩着办大事!
- 树莓派制作无线路由器
- android4.2 拦截power键,Android 屏蔽Power键 Home键
- [Vue warn]: Invalid component name: “.-pages-smartRecommendation-questionStart-questionStart“. Comp
- DMIPS CPU主频
- Holm–Bonferroni method
- Nesterov加速算法