Write once, run anywhere | Nebula Hackathon 2021 背后的参赛者们

Write once, run anywhere

为期一个多月的首届 Nebula Hackathon 2021 同 2021 年一般结束在年底,来自国内外参赛队伍同场角逐,比拼技术和创意。本届 Hackathon 是 Nebula 社区主办的第一届黑客马拉松,主题为:探索未知,从内核到周边,周边延伸到上层应用,让广大图数据库及 Nebula 爱好者 SHOW 尽图世界。虽然比赛告一段落,不过参赛队伍同 Nebula 的故事正开始…在本系列#Nebula Hackathon 背后的参赛者们#中你将看到他们是如何将灵感映射到 Nebula 中的

第一期同大家见面的是本次活动的《最佳项目奖》获得者——星云之巅。

星云之巅在本次 Nebula Hackathon 2021 中为大家带来一个「UDF Enhance Nebula」项目,他们致力为 Nebula Graph 实现第一个生产级用户自定义函数(UDF,User Defined Function)引擎。当内建函数无法支撑业务实现时,用户可以自行编写代码逻辑来创建在数据库上直接运算的自定义函数满足其多样化需求。

队名由来

星云之巅的队长王国彬是一个魔兽世界爱好者,魔兽世界中有一个他比较喜欢的一个关卡叫旋云之巅,而 Nebula 本身正好是星云的意思,所以队名也由此诞生了。星云之巅一共有 2 位成员,除了来自百度的王国彬队长之外,还有一位来自华为的赵祯真。他们是毕业于同一所大学的校友,一个身处上海,一个身处深圳,虽然隔着 1680 多公里,但是 Nebula Hackathon 2021 给他们建立起强协作关系。

在分工上,王国彬负责比赛的整体设计、功能规划、Demo 制作、Presentation 以及具体实现中的 WASM 相关模块;赵祯真则负责具体实现中的语法解析模块。

灵感来源

UDF 顾名思义是由用户提供的函数。在数据库领域,UDF 代表一种机制:通过添加一个函数来扩展数据库服务的功能

在队长王国彬报名后的很长时间,大概在一个星期他都没项目名提交给 Hackathon 工作人员,突然有一天国彬说:“我要用 WASM 做一个 UDF Enhance Nebula。”

WASM 全称 WebAssembly,是一个可移植、体积小、加载快并且兼容 Web 的全新格式。它最核心的能力就是安全,可以在一个平台上运行不可信任的代码。

问及为什么要做这个项目时,王国彬表示“年初在 TiDB 2020 Hackathon 中了解到 ’ or 0=0 or ’ 的这个项目,其赛后的通稿让我了解到了 WASM 在服务端作为拓展机制的潜能” 。正是由于前人“种树”,相当于二次实践的星云之巅在演示时,着重选取了基于 Rust 编写的字符串拼接、辗转相除求最大公约数、Socket 网络请求——飞书聊天机器人、逆波兰表达式计算器这 4 个 Demo 来侧重展示 WASM 技术场景的丰富性

SHOW YOUR CODE

在 Nebula 社区中,像之前 @zhaochuanyun 就提过 Nebula 会计划支持 UDF 的问题,方便他们将数据加载和计算直接落到 Nebula Graph 平台,从而省去加载数据的开销,满足时效性要求。而这个功能由于优先级的问题,暂时 Nebula 官方尚未开发。正如国彬在演示(见文本末)中讲的那样,未来 Nebula 也许会成为一个 DBaaS 平台,传统 SaaS 产品通过 HTTP 请求和回调为外部应用程序提供 API。如果这时候 DBaaS 平台允许类似 UDF 这样的用户自定义代码直接上传到平台本身,开发者就不需要维护处理回调的中间层,更好的利用 Nebula 的内部 API,安全高性能的同时也保证了更高的可拓展性

但一切并非顺风顺水。技术难题是在研发进程中不断产生的,很多是王国彬和赵祯真一开始没意识到的。

在研发初期首先碰到的是编程语言和编译问题,此前没有接触过 C++ 大型项目,二人沉下心来反复阅读源码,“得益于 Nebula 代码简洁干净,分层合理,我们能够短时间内掌握大部分实现细节,并且成功编译以及调试程序,一步一步跟踪运行明白了调用链。” 快速入门 C++ 开发的王国彬透露了他的学习法。在研发中期跑通了流程后,王国彬和赵祯真发现现在 UDF 功能非常单薄,只支持像加减法、辗转相除求最大公约数这种纯数字的 UDF 函数。“能不能整点有意思的呢?”他们想到去实现一个飞书聊天机器人。这需要去实现 WasmEdge 虚拟机下的字符串类型参数传递以及 Socket 请求,其中字符串类型参数传递功能需要将字符串从宿主机内存映射到虚拟机内存,WasmEdge 的官方 C++SDK 没有提供直接这个特性的接口,都是比较底层的接口,开发一度卡顿。后来他们发现支持这个特性的官方 Go SDK 是基于 CGO 实现,了解了里面的内存映射关系实现了这个功能,“这里也挺感谢 WasmEdge 社区提供的帮助”王国彬说道。最终 4 个演示 Demo 里面的 3 个是在比赛截止时间的前 2 个小时才完成的,非常惊险。

他们交上来了怎么样一份考卷呢?这是星云之巅 UDF 的架构图:

Write once, run anywhere

UDF Enhance Nebula 架构简单分为下面四个模块:

编译工具链:作用是快速转换已有代码成 WASM,王国彬透露:“这个模块比较杂乱,是我们开发调试使用 WASM 程序,面向比赛 Demo 使用的。”

语法解析:基于 Flex 与 Bison 实现创建函数,删除函数的 SQL 语句。实现语法可以见下图,这里考虑到 WebAssembly 文本格式(wat),WASM 二进制文件两种主流的格式。以及其加载方式,分为两种,第一种是方便在终端里直接输入的 wat base64 编码以及 WASM 二进制文件 base64 编码,运行大小在 KB 级别的程序可以直接引入,第二种是 MB 级别的 WASM 程序二进制文件,支持通过 HTTP 地址引入以及本地文件地址引入。

Write once, run anywhere

函数管理:负责对 WASM 虚拟机进行统一管理,提供函数的动态更新、加载、卸载功能。也可以说是 Nebula 其他系统与 WASM 拓展交互的中间胶水。

当有函数创建时,将语法解析后得到的函数名称、运行参数、返回参数、函数本体。针对不同的函数注册方式,通过 base64 解码、HTTP 下载、文件读取三种操作手段对本体进行加载,加载后调用虚拟机接口进行编译,得到编译后的沙盒。将函数运行参数,返回参数,沙盒进行组合拼接成一个可以后续直接虚拟机使用的函数运行对象。以函数名称为 Key,函数运行对象为 Value 存储在内存 Map 中。

在函数被调用时,根据函数名称找到函数运行对象,对传入参数进行参数校对以及参数转换成虚拟机可以接受的参数,调用虚拟机执行沙盒,得到返回参数,将返回参数转换成Nebula内的数据类型,返回上层系统。

当有函数删除时,即删除内存中的函数运行对象。

虚拟机:这里主要是引入 Wasmtime,WasmEdge 两个虚拟机的 C++ SDK,通过调用 SDK 来实现 wat,WASM 二进制文件编译执行,沙箱实例管理,WASI 特性管理等。

Write once, run anywhere

留给未来

Nebula Hackathon 2021 是一个极限挑战,在特定时间内验证你的想法,正如所有的 Hackathon 参赛项目一样,星云之巅的 UDF Enhance Nebula 也留有遗憾:“第一是我们其实没有充分利用到 Nebula 架构的优势,实现的手法比较 Hack,代码都在 Graph 模块里面的 Parser、Validator 两个流程里面。Storage、Meta 两个模块我们没有使用,函数都存储 Cache 在内存里,这算是一个比较大的问题。另外作为一个函数引擎来说,最好是有完整的 Planner,Scheduler ,Executor 的生命周期,这些抽象是保证函数高效执行的必要方式

第二是在 WASM 程序内部调用 Nebula 系统的 API 这个工作没有完整实现,受制于 WASM 的安全机制,任何对外部资源的访问必须通过导入模块来间接实现,需要将 Nebula 的内部 API 的入参出参上再加一层数据转换传入到 WASM 内部,尝试了一下被 WASM 支持的有限数据类型卡住了,这个中间层需要大量的工作。如果这个工作可以完成,我们甚至可以通过 WASM 暴露 Nebula 内部指标,做可观测性上的工作

第三是我想做的一些更能展示 WASM 能力的 Demo 没有完成,超越现在传统定义的 UDF,比如在 WASM 内部加载一个结构化数据的模型,读入 Nebula 存储的数据,跑一个简单的聚类或者回归,以及将一个完整的图算法编译成 WASM。长远来看,我们也可以在很多地方嵌入 WASM 拓展,实现自定义 Parse、鉴权、审计等复合需求

这次比赛中,我们亲身体会到 WASM 在服务端作为拓展机制的潜能,但是也发现这个方法从玩具到落地需要更多的工程实践。比如说 WASM 函数的管理,宿主机与 WASM 扩展程序之间的交互设计,可观测性如何做、函数调用规范、数据传输规范、调试方法等等。这里有非常多的坑需要去踩,绝对不是简单的拿一个虚拟机过来糊一层胶水完事。我们想去为这个探索的过程做一点微小的贡献,提炼我们在本次比赛中的经验和教训,开源一套支持多语言的 SDK,抽象宿主机和 WASM虚拟机之间的交互,方便更多软件来嵌入 WASM 拓展机制,甚至能形成一套最小化可实行的规范,未来我们计划将这些成果回馈到 Nebula 社区。”

回到 Nebula Hackathon

在采访的最后,我们问了星云之巅队长王国彬他们对其他项目及参赛队伍的印象。王国彬给出了 Marauders 的名字:“图数据库是非常适合表达血缘关系,非常天然,通过点边结构可以将血缘的链路上下游进行完美串联,进而实现链路存储计算检索分析。再者现在讲数据湖架构比较多,数据湖相对于传统数仓有新的数据治理体系,就是数据生命周期的管理,元数据管理这些点。综上我认为这个项目是比较贴合图数据库本身以及业界需求的,还有的话就是界面很酷,看起来交互挺好玩。”


这是一个从 https://nebula-graph.com.cn/posts/nebula-hackathon-2021-team-interviewing-01/ 下的原始话题分离的讨论话题