点赞
评论
收藏
分享
举报
WebAssembly 组件模型 — 原因、方法和内容(第 1 部分)
发表于2025-03-12 17:07

浏览 2.3k

原文作者:Timo Stark - F5 专业服务工程师
原文链接:WebAssembly 组件模型 — 原因、方法和内容(第 1 部分)
转载来源:NGINX 开源社区

NGINX 唯一中文官方社区 ,尽在 nginx.org.cn

   


   

如果您有兴趣开始使用 WebAssembly 组件模型,但面对庞大的生态系统不知从何处着手吗?如果是,那么本文正适合您!


在本文中,我们将分享一些经验和心得,它们是我们在向 NGINX Unit 中添加对 WebAssembly 组件模型的支持时所获得的——感谢我们强大而活跃的社区。


如果您已经熟悉 Wasm 生态系统,或者只是想了解如何编写代码,请关注本账号,参考本系列博文的第二篇。

 

WebAssembly 组件模型和 NGINX Unit

在推出第一版 Unit Wasm 语言模块之后,我们做了许多工作。在 2023 年 9 月,我们说过:


我们将 WebAssembly 支持作为技术预览版推出,希望尽快代之以 WASI-HTTP 支持。


我们在 Unit 1.32.0 中做到了这一点。该版本支持将 WASI 0.2 API 和 wasi:http/proxy world 用作其主接口的 Wasm 组件。


此处注意,如果前面有你不熟悉的词汇,也不要担心。本文将介绍 WebAssembly (Wasm) 组件模型的概念,以及 WebAssembly 系统接口 (WASI) 在其中所扮演的角色,还将探讨“WebAssembly 接口类型”的意义。


正如之前的博文中所述,Wasm 运行时与 Wasm 模块通过共享内存以原始字节的形式共享数据。要理解此字节流,主机和 Wasm 模块必须如出一口,或者从技术上说,实现相同接口。NGINX Unit 的核心概念是创建一个与特定应用相关的 HTTP 请求的上下文,并与运行时共享内存中的这组字节。


这正是我们在 unit-wasm 中所做的。虽然学习如何向 Unit 添加 Wasm 支持既有趣也很有必要,然而这与实现或采用某一标准相去甚远,因此就需要 Wasm 组件模型上场了。


WebAssembly (Wasm) 组件模型明确了不同的 Wasm 模块或组件之间及其与运行时环境之间的通信方式。它建立了必须满足的特定契约,以确保编译到 Wasm 组件中的代码可以托管在兼容的运行时上,并在运行期间与其他 Wasm 组件无缝交换数据。


如需获取这一理论框架的应用示例,请查看 NGINX Unit 中的实现,它是典型的 Wasm 组件模型实例。


Wasm 组件模型的两个重要组成部分是 WebAssembly 系统接口 (WASI) 和 WebAssembly 接口类型 (WIT)。下面我们来详细了解一下这两个标准。

 

WASI 和 WIT

WASI 是“WebAssembly System Interface(WebAssembly 系统接口)”的缩写,由 Wasmtime 项目推出,专为 Wasm 而设计。它是 Wasm 的可移植系统接口,支持访问多项操作系统的功能,包括文件和文件系统、套接字、时钟、随机数等。为什么需要它?


因为我们现在创建的 Wasm 组件是针对服务器端运行时而非基于浏览器的 Wasm 运行时(使用 Web API 或 JavaScript)。浏览器之外的代码需要一种方式来与底层系统通信。为了更好地理解 WASI 的作用,我们用 Rust 编写了一个非常简单的程序,它会输出“Hello World”。


我们编写的代码可以编译成一个可执行的二进制文件。程序启动后,我们会看到命令行上输出“Hello World”。这背后其实是 POSIX 标准在发挥作用,它定义了系统调用。系统调用在不同操作系统上的工作方式不同。


WASI 为这些系统调用提供了一个抽象层,可供编译到 Wasm 的代码使用。兼容 WASI 的运行时能够处理该代码的执行。我们将在本系列博文第二篇的 Rust 教程中进一步介绍其实际应用。自 WASI 提案的 Preview2 开始,WASI-API 在 WIT 文件中进行定义。


WIT(Wasm 接口类型)是一种用于定义接口的描述性接口描述语言 (IDL),而非一种通用编码语言。编写的 WIT 文件不包含任何业务逻辑,只是纯粹的契约定义。多个接口可以进一步组合为 ”world”。虽然深入了解如何创建自己的 WIT 文件不是必需的,但有助于在构建组件时查找问题或排除故障。


Wasm 组件模型和 wasi:http/proxy world 使用的 WIT 文件由字节码联盟 (Bytecode Alliance) 创建和维护。截至本文撰写之时,使用它们的最佳方式是通过 Wasmtime 项目的 GitHub 代码库,以及进行手动拉取。


WIT 文件的一个有趣之处在于其版本控制系统。由于实现 Wasm 运行时的主机以及我们将要构建的组件都在为 WIT 文件定义的契约创建绑定,因此我们必须指向这些契约的同一版本,或者选择支持多个 WIT 文件版本的运行时。这值得再写一篇博文。现在,我们只考虑最新的稳定版本,它发布于 2024 年 2 月,标记为 WASI 0.2。该版本包括 wasi:cli world 和 wasi:http world。


在 WebAssembly 生态系统中,这些契约被称为“world”,下文将使用这一术语。就 NGINX Unit 用例而言,我们的目标非常明确,那就是 wasi:http/proxy world。您可以将 wasi:http/proxy world 视为一组描述 HTTP 请求和响应的接口,包括所有数据(HTTP 方法、请求头、正文等)。如果您是老 Web 开发人员,这可能会让您想起 CGI。

   

NGINX Unit、Wasmtime 和 Rust — 运行时实现

经过上面的介绍,我们现在知道 WASI/WIT 在支持组件模型方面扮演重要角色。作为站点,Unit 必须实现 WIT 文件定义的 WASI HTTP 代理接口才能履行契约。对此我们早已知晓。那既然使用 Wasmtime 作为 Wasm 运行时,我们何不将此任务委托给运行时呢?


当然,完全可以!不过,有一个虽不起眼但很重要的细节:我们当时的实现完全是用 C 语言编写的,使用的是 Wasmtime C-API。遗憾的是,这些 API 缺乏支持组件模型的必要功能。


正如本文开头所述,只要找到对的人,心往一处想,再复杂的挑战均可迎刃而解。无论过去还是现在,Fermyon 都是我们极具价值的重要合作伙伴。经过一场 Slack 和 Zoom 深夜会议后,我们发现在 Wasmtime C-API 中添加对组件模型的原生支持过于复杂。此外,没有 bindgen 等自动化工具的帮助,使用 WIT 文件手动实现接口将需要大量维护工作。


在向 Fermyon 解释 NGINX Unit 的内部结件和当前基于 C 语言的语言模块的工作原理后,他们分享了一个支持 Wasmtime 的 Rust API 的基于 Rust 的 Unit 语言模块原型。再没有 C-API 的什么事了。


现在,我们准备好开始写代码了。

 

后续

在下一篇中,我们将介绍使用 Rust 和 WASI 0.2 API 创建 Wasm 组件的流程。

 


 

NGINX 唯一中文官方社区 ,尽在 nginx.org.cn

更多 NGINX 相关的技术干货、互动问答、系列课程、活动资源: 开源社区官网 | 微信公众号 | B 站

已修改于2025-03-12 17:07
本作品系原创
创作不易,留下一份鼓励
NGINX官方账号

暂无个人介绍

关注



写下您的评论
发表评论
全部评论(0)

按点赞数排序

按时间排序

关于作者
NGINX官方账号
这家伙很懒还未留下介绍~
331
文章
21
问答
201
粉丝
相关文章
介绍nginx网页配置工具QQ技术交流群1:1106758598QQ技术交流群2:560797506邮箱: cym1102@qq.com官网地址: http://www.nginxwebui.cn码云: https://gitee.com/cym1102/nginxWebUIgithub: https://github.com/cym1102/nginxWebUI功能特点nginxWebUI也可管理多个nginx服务器集群,随时一键切换到对应服务器上进行nginx配置,也可以一键将某台服务器配置同步到其他服务器,方便集群管理.部署此项目后,配置nginx再也不用上网各种搜索配置代码,再也不用手动申请和配置ssl证书,只需要在本项目中进行增删改查就可方便的配置和启动nginx。技术说明本项目是基于springBoot的web系统,数据库使用sqlite,因此服务器上不需要安装任何数据库项目启动时会释放一个.sqlite.db到系统用户文件夹中,注意进行备份本系统通过Let'sencrypt申请证书,使用acme.sh脚本
点赞 6
浏览 23.4k
  前三周学习了陶辉老师的“NGINX基础培训系列课程”,感觉受益良多,在这里想把一些知识点记录一下,和大家分享一下知识点,也方便日后的随手查看,温故知新。  首先,我们了解到了Nginx的版本,Nginx发布版本分为主线版本和稳定版本,区分两个版本也非常简单,主线版本版本号为单数,比如1.19,稳定版本为双数,比如1.18,今天我要说的是稳定版本,这个版本会尽量少的减少Nginx的bug问题,适用于生产环境,这里我不建议使用Nginx和其他软件一样在生产环境中落后一个或多个大版本使用,之前生产环境做过漏扫,发现我们编译自带的Nginx版本为:nginx/1.13.3(查询命令为nginx-V),结果出现了多个漏洞,四个高危和一个中危漏洞:        通过升级Nginx到稳定版最新版本后修复!  其次,是Nginx发行版本的选择,目前比较流行的有:nginx、nginxplus、Tengine、openresty、ope
点赞 1
浏览 16.8k
感谢您参加“NGINX从入门到精通进阶系列培训”!以下为培训的问答、课件和录像,希望您能通过此培训学有所得,祝学习进步!>问与答:- 基础篇+高级篇 - 应用篇+实战篇(New)>课件(PPT):基础篇:-NGINX概要、安装、配置:https://interact.f5.com/rs/653-SMC-783/images/CNFEB22-NginxCoreCourse-Setup.pdf-NGINX日志、运维:https://interact.f5.com/rs/653-SMC-783/images/cnfeb22-nginxcorecourse-maintenance.pdf高级篇:-NGINX变量、API:https://interact.f5.com/rs/653-SMC-783/images/CNFEB22-NginxCoreCourse-API.pdf-NGINXSSL、NJS:https://interact.f5.com/rs/653-SMC-783/images/CNFEB22-NginxCoreCourse-SSL.pdf
点赞 10
浏览 19.3k