This article also has an English version.
本文将介绍我写的一个 Rust 调用 Golang FFI 框架的设计与实现,从设计和实现者的角度设计多种方案并给出选择和原因,以及介绍一些实现细节。
项目已开源于 Github:https://github.com/ihciah/rust2go。
相比 Golang,Rust 程序没有 GC,并且有更强的编译检查,基于 LLVM 获得了最强的编译优化,所以拥有更好的性能和安全性。
在字节跳动内部,为了推动成本优化,我参与了 Rust RPC 框架开发,并带头实现了服务发现、metrics、log、动态配置等多个业务必要的 Rust SDK,以及提供了编译与运行镜像、crates 内部源和公网镜像(rsproxy.cn)等。在这些基建之上,多个核心业务迁移至 Rust 并取得了较大的性能收益:CPU 占用降低 30% 以上,部分延迟敏感业务 P99 显著降低。但是,这些业务很多是不需要积极维护的,例如代理、缓存类,有较复杂且积极迭代的业务逻辑的服务则较难迁移 Rust。
理论上我们可以将所有 Golang 程序使用 Rust 重写以获得更好的性能,但是实际操作中仍存在较大困难:一是重写全部 Golang 依赖组件不一定现实,二是一口气完成全部重写较为困难。如果提供一种从 Rust 高效调用 Golang 的手段,能够让业务可以循序渐进地完成 Rust 重构,那么这两个问题都可以解决。
本文涉及内容较多,整体叙述脉络:首先讨论整体方案的选型并给出一个极简 PoC;之后从这个极简 PoC 入手,扩展并细化该方案以支持必要的特性;最后会从框架实现角度介绍一些值得讨论的实现细节。