
今天,我们宣布Cloudflare Workers试验性支持WASI(WebAssembly系统接口),并在wrangler2中提供支持,以便大幅提升工作便利性。我们一如既往对Primer整个WebAssembly生态系统充满希望,并十分积极地采纳新开发的标准。
WebAssembly快速入门
那么,WASI到底是什么呢?若要了解WASI以及我们对其充满希望的理由,就有必要快速回顾一下WebAssembly以及它周边的生态系统。
借助WebAssembly,使用编译语言编写的代码未来有望能够编译为通用二进制格式并以接近原生速度的速度在安全沙盒中运行。虽然WebAssembly是围绕浏览器设计的,但模型迅速扩展到服务器端平台,例如Cloudflare Workers(自2017年以来一直支持WebAssembly)。
WebAssembly最初设计为与Javascript一起运行,并需要开发人员直接与Javascript交互才能访问沙盒之外的内容。换句话说,WebAssembly并没有为I/O任务提供任何标准接口,例如与文件交互、访问网络或读取系统时钟。这意味着,如果要响应外部事件,开发人员需要负责在JavaScript中处理该事件,并直接调用从WebAssembly模块导出的函数。类似地,如果要从WebAssembly中执行I/O,就需要在Javascript中实现该逻辑并将其导入WebAssembly模块中。
Emscripten等自定义工具链或wasm-bindgen等库应运而生,用于简化这一工作,但它们特定于语言,会带来极大的复杂度,并且使代码显得十分臃肿。我们甚至构建了自己的库workers-rs,使用wasm-bindgen以试图让在Rust中编写应用程序感觉就像在Worker中原生那样–但最后我们发现,这不仅很难维护,而且还需要开发人员编写特定于Workers的代码,并且这些代码无法移植到Workers生态系统之外。
我们需要更强的功能。
WebAssembly系统接口(WASI)
WASI旨在提供任何编译到WebAssembly的语言都可以作为目标的标准接口。点击此处阅读Lin Clark的原创文章,其中很漂亮地做了介绍–甚至还做了代码卡通。简而言之,Lin将WebAssembly形容为适合“概念机器”的汇编语言,而WASI则是适合“概念操作系统”的系统接口。
这种系统接口标准化为现有工具链针对wasm32-wasi目标交叉编译现有代码库铺平了道路。通过wasi-sdk和Rust工具链已经实现了极大进展,尤其是在Clang/LLVM中。这些工具链利用某个版本的Libc,它提供POSIX标准API调用,这些调用是在WASI“系统调用”基础上构建的。甚至在TinyGo和SwiftWasm这样更为边缘化的工具链中也有基本实现。
实际说来,这意味着现在可以编写的应用程序不仅能够与实现该标准的任何WebAssembly运行时互操作,还能与任何符合POSIX标准的系统互操作!这意味着,完全相同的“Hello World!”可在本地Linux/Mac/Windows WSL机器上运行。
代码细节
WASI听起来很不错,但它能真正简化编程工作吗?谁用谁知道。我们来看一个例子,看看它如何运用于实践。
首先,生成一个基本的Rust“Hello,world!”应用程序,对其进行编译并运行。
这是再简单不过的了。可以看到,我们只定义了一个main()函数,接着是用一个println语句打印到stdout。
现在,我们针对wasm32-wasi目标编译这个程序,并在Wasmtime等“现成”的wasm运行时中运行。
太棒了!相同的代码在多个POSIX环境中顺利编译并运行。
最后,来看看我们刚才为Wasmtime生成的二进制文件,但这次改用Wrangler2将其发布到Workers。
不出所料,成功了!相同的代码兼容了多个POSIX环境,并且相同的二进制文件兼容了多个WASM运行时。
在云中运行CLI应用
细心的读者可能会注意到,我们在通过cURL发出的HTTP请求中做了一点手脚。在这个例子中,我们实际上是分别使用HTTP请求和响应主体来与Worker之间进行stdin和stdout流传输。利用这个模式,可以实现一些非常有意思的用例,具体来说,设计为在命令行中运行的程序可以作为“服务”部署到云中。
“Hexyl”就是一个完全开箱即用的例子。这里,我们对本地机器上的二进制文件执行“cat”命令,并通过“pipe”命令将输出输送到curl,后者会通过POST命令将输出发布到我们的服务,并流传输回结果。按照我们用于编译“Hello World!”的步骤,我们可以编译hexyl。
无需任何修改,我们就能利用一个现实的程序来创建立即就能运行或部署的用例。同样,我们让wrangler2预览hexyl,但这次给它提供一些输入。
点击https://hexyl.examples.workers.dev,自己试一试。
一个更有用、但也更复杂一些的例子就是将swc(swc.rs)等实用工具部署到云中并将其用作按需JavaScript/TypeScript跨平台编译服务。这里,我们可以执行几个额外步骤,确保编译的输出尽可能小,但除此之外,它基本上是开箱即用的。这些步骤在https://github.com/zebp/wasi-example-swc中详述,但目前我们只是粗略概括一下,看看托管示例。
$ echo “const x = (x, y) => x * y;” | curl -X POST –data-binary @- https://swc-wasi.examples.workers.dev/ –output -var x=function(a,b){return a*b}
最后,我们还可以对C/C++执行相同的操作,但需要做一些修改,将Makefile调整正确。这里有一个例子,说明如何编译zstd并将其上传作为流传输压缩服务。
https://github.com/zebp/wasi-example-zstd
如果我想在JavaScript Worker中使用WASI
该怎么办?
利用Wrangler,可以非常轻松地部署代码,不用管Workers生态系统,但在一些情况下,可能实际上需要从Javascript调用基于WASI的WASM模块。这可以使用以下简单样板来实现。https://github.com/cloudflare/workers-wasi中将保留一份更新的README。
现在借助JavaScript样板和wasm,我们可以利用Wrangler的WASM功能轻松部署Worker。
回到未来
过去几十年积极关注编程发展的读者可能会注意到,这非常类似于RFC3875,也就是我们常说的CGI(公共网关接口)。虽然我们这个例子显然不符合该规范,但不难想象,完全可以加以扩展,将基本“命令行”应用程序的stdin转变为完全成熟的http处理程序。
在此,我们非常渴望了解开发人员对此有何看法。请在Discord或Twitter上与我们分享您所构建的成果!
图片来源:图虫创意 小喇叭:上篇娜姐分享文章:如何安全高效的提升listing的留评率? 娜姐每天的操作日志及心得在这里分享给大家,还没关注的赶紧来噢! 文 : 娜姐 “全面激活listing”对于提升亚马逊销售额和产品排名是极为重要的。 只有将listing…
码刀科技(www.lekshop.cn)是国内知名企业级电商平台提供商,为企业级商家提供最佳的电商平台搭建(多种模式电商平台搭建:B2B/B2B2C/B2C/O2O/新零售/跨境等)、平台管理系统开发及互联网采购解决方案服务, 联系客服了解更多.