多年来,[WebAssembly0 解决了一个明确定义的问题:在浏览器中以接近本机的性能运行编译语言的代码。但有一个令人沮丧的限制。每个 Wasm 模块都是一个岛屿。你可以将 Rust 编译为 Wasm,公开函数并从 JavaScript 调用它们,但如果你想要一个 Python 模块与 Rust 模块对话,你必须编写手动粘合,粘合代码在两侧序列化和反序列化数据,就像低级 FFI 一样。真正的便携性的承诺并没有达到组合物。
组件模型是缺失的一块,随着 2024 年初的 WASI 0.2,它开始起步并成为生产基地。
组件模型解决的问题
传统的 Wasm 模块公开并使用原始类型的函数:整数、浮点数、线性内存指针。公共合约中没有字符串、记录或列表的原生概念。当两个模块需要交换数据时,开发人员有责任定义序列化约定,将指针传递给共享缓冲区,并确保双方都同意格式。
这在一种语言中有效。一个 Rust 模块调用另一个 Rust 可以建立约定,因为双方都理解相同的抽象。在多语言场景中,这种安排成为您编写、维护并最终以微妙方式破坏的粘合代码。
WIT:组件之间的契约
核心组件模型解决方案是 WIT(Wasm 接口类型),这是一种与语言无关的 IDL,用于描述组件公开的内容以及需要使用的内容。您编写一次接口,每种语言的工具都会自动生成实现或调用它所需的代码。
将 WIT 视为 Protobuf,但用于同一进程内的组合而不是网络上的消息。合约描述了具有丰富类型、字符串、列表、命名记录、可能出错的结果的函数,并且工具负责每种语言的表示和组件的规范格式之间的转换。
实际结果是,处理字符串的 Rust 组件可以由具有业务逻辑的 Python 组件调用,该业务逻辑为 JavaScript 序列化组件提供数据。无需手动序列化,无需网络跳跃,使用 WIT 生成的粘合代码而不是手动编写。
WASI 0.2 和转向生产
2024 年 2 月发布的 WASI 0.2 是一个里程碑,它使组件组合成为真正的团队可以采用的东西。 WASI 的早期版本定义了 Wasm 模块如何访问操作系统,但它早于组件模型并使用旧的扁平模块模型。 WASI 0.2 在组件模型之上进行了重写:所有系统接口、文件读取、网络、时钟、随机性现在都是 WIT 合约。
具体结果是,依赖 WASI 进行 I/O 的组件依赖于标准化的 WIT 接口,而不是特定的实现。运行时可以在不同的环境中以不同的方式满足这种依赖关系,在服务器上、在边缘上、在浏览器中通过polyfill,而无需重新编译组件。可移植性不再是一种愿望,而是成为一种可验证的财产。
随附的工具链包括作为参考运行时的 wasmtime、用于组件组合的 wasm-tools 以及用于 JavaScript 生态系统的 jco,它将 Wasm 组件从 WIT 定义转换为原生 ES 模块。
谁在使用它以及在哪里使用它
最成熟的采用场景是基于 Wasm 的无服务器平台。 Fermyon with Spin 和 Fastly with Compute 将组件模型视为本机部署单元。开发人员用 Rust 编写组件、编译、部署,运行时负责与 HTTP、键值数据库和其他平台服务的 WASI 接口进行组合。
字节码联盟(ByteCode Alliance)是指定组件模型的联盟,成员包括 Fastly、Intel、Mozilla 和 Microsoft,这为项目提供了规范项目有时缺乏的制度稳定性。
目前尚未大量存在的是原生打包为 Wasm 组件的库和框架。现在你可以将很多东西编译成组件,但是与 npm 包或 Rust 箱子相比,已发布和可重用组件的存储库很小。该组合在技术上是可行的,但零件目录仍在构建中。
尚未解决的问题
Rust 拥有当今最完整的组件模型支持。 Go 和 Python 都有可用的工具,但编译完全支持 WIT 类型的组件仍然会产生摩擦。这不是阻塞,而是一个重要的堆栈决策:不使用 Rust 的团队会遇到粗糙的情况。
调试多语言组件图确实比调试 [monolith] 更困难。存在语言边界、组件之间的内存隔离以及不透明地跨越这些边界的堆栈跟踪。工具不断改进,但这些类型的问题往往出现在开发周期的后期。
组件之间的交叉调用也存在开销。它不是网络跃点的成本,但与同一进程内的调用相比是可以测量的。在大多数情况下,这种成本消失在组件实际工作的噪音中。在高频热路径中,需要仔细考虑组合的粒度。
领导者的架构决策
对于当今评估组件模型的团队来说,最有用的问题不是“准备好了吗?”但“准备好做什么?”。对于 Rust 来说,答案是肯定的,但对调试工具有所保留。对于 Go 或 Python 团队来说,答案是“它可行,但在提交之前至少有一名了解该领域的工程师。”
组件模型解决了一个没有好的解决方案的问题:跨语言边界编写软件,而无需支付网络边界的成本。如果您正在构建可扩展性平台,该模型保证可验证的 WIT 合约而不是不受限制的本机代码。如果您有使用不同语言的团队需要共享繁重的计算逻辑,那么具有 WIT 接口的 Wasm 组件是当今最干净的替代方案。
对于那些不处于这些情况的人来说,现在从概念上了解模型就足够了。 2025 年有意义的决定将在 2027 年变得更加明显,届时组件目录和语言支持已经成熟。
另请阅读
- [面向领导者的 WebAssembly:当架构决策值得时3
- [浏览器之外的 WebAssembly:缺失的通用执行层4
- [WebAssembly 处于边缘:为什么快速启动和隔离很重要55
- [边缘计算:为什么分布式处理将重新定义您的架构6
- [用于插件和沙箱的 Wasm:安全运行第三方代码7
- [巴西 Rust 和 WebAssembly 搜索量的增长:技术趋势分析88