WebAssembly现在和未来应用场景大全 - harshal


WebAssembly(缩写为 Wasm)是各种编程语言和许多不同执行环境之间的中间层。您可以获取用 30 多种不同语言编写的代码并将其编译为 .wasm 文件,然后可以在浏览器、服务器甚至汽车上执行该文件。
“WebAssembly”这个名称具有误导性。虽然它最初旨在使代码在 Web 上快速运行,但现在它也可以在浏览器之外的各种环境中运行。此外,WebAssembly 不是汇编,而是稍微高级一点的字节码。
 
WebAssembly 的优势在哪里?
WebAssembly 之所以出类拔萃,是因为以下五个特点:

  • 可移植性:Wasm 字节码的二进制格式是标准化的,这意味着任何能够执行 Wasm 的运行时都可以运行任何 Wasm 代码。1这类似于 Java 的“一次编写,随处运行”的承诺。在浏览器中,95% 的用户浏览器都可以执行 WebAssembly,剩下的差距可以使用 wasm2js 编译器来弥补。对于服务器,有WasmtimeWasmer等运行时。即使是资源受限的物联网设备也可以使用WAMR加入乐趣。2
  • Universal统一:许多语言都可以编译成 Wasm。这种支持超越了 C、C++ 和 Rust 等系统语言,包括垃圾收集的高级语言,如 Go、Python 和 Ruby。可以在此处找到编译为 Wasm 的语言的完整列表。
  • “Near-Native 性能”:Wasm 通常被描述为具有“Near-Native 性能”。这实际上意味着 WebAssembly 几乎总是比 JavaScript 快,尤其是对于计算密集型工作负载,并且平均比原生代码慢 1.45 到 1.55 倍,但结果确实因运行时而异
  • 快速启动时间:Wasm 的冷启动时间非常重要,它保证了它自己的一个类别。在服务器上,它可以实现比 Docker 容器快 10-100 倍的冷启动,因为它不需要为每个容器创建新的 OS 进程。在浏览器中,解码 Wasm 并将其转换为机器代码比解析、解释和优化 JavaScript 更快,因此 Wasm 代码可以比 JavaScript 更快地开始以最高性能执行。
  • 安全:WebAssembly 的设计考虑到了 Web,因此安全性是重中之重。在 Wasm 运行时中运行的代码是内存沙盒和功能受限的,这意味着它仅限于执行明确允许执行的操作。5在沙盒中,Wasm 代码仍然可以被授予访问底层系统的权限,包括系统级接口和硬件功能。

 
WebAssembly 在哪里有用?
1. 加速 JavaScript
Wasm 及其前身 asm.js 背后的最初动机是加速 Web 上的客户端代码,并且有很多 Wasm 在这个领域表现出色的例子:
  • 例如,Figma 设计工具的核心是用 C++ 编写的,然后编译为 WebAssembly。他们发现使用C++ 编写在性能和可用性方面取得了重大优势,同时[url=https://www.figma.com/blog/webassembly-cut-figmas-load-time-by-3x/]编译为 WebAssembly[/url]将加载时间缩短了 3 倍,并显着减少了下载大小。
  • 当切换到 Wasm 时,密码管理器 1Password 在表单繁重的网站上实现了13-39 倍的加速。Wasm 性能也比 JavaScript更一致,这对于延迟敏感的应用程序很重要。

  
2. 编程语言互操作性
WebAssembly 让我们更容易跨越编程语言之间的界限。库和框架通常是用一种语言编写的,这使得在不完全重写的情况下很难使用其他语言的代码。使用 WebAssembly,我们可以更轻松地执行用其他语言编写的代码。这使我们能够重用代码,而不是重新发明轮子。
目前,这主要用于将应用程序移植到网络上。这里有一些例子:
  • Figma 使用名为 Skia 的低级 C++ 库来处理一些图形算法,而不是构建自己的算法或将它们移植到 JavaScript。
  • 我最喜欢的国际象棋服务器 lichess.org 在用户的浏览器中运行世界级的 Stockfish 国际象棋引擎,从而为他们节省了在服务器端运行它的计算负担。
  • Google EarthAdobe Photoshop使用 Wasm 将他们的 C++ 代码库移植到了网络上。

将应用程序移植到 Web 是最容易开始的地方,而且我们很可能会看到这种趋势继续下去。但是,Wasm 的互操作性不仅限于浏览器。它还被用于使代码跨平台和跨设备工作:
  • Uno 平台是一个 UI 平台,可让您编写单个应用程序并让它在 Windows、macOS、iOS、Android、Linux 和浏览器上运行。它似乎相当以 Windows 为中心,因为应用程序是用 C# 和 XAML 编写的,因此许多用例都基于减少将旧应用程序移植到新平台所需的工作量。
  • Amazon PrimeDisney+BBC都在其视频平台中使用 WebAssembly。例如,Amazon Prime 使用它为各种设备类型提供新功能,同时保持可接受的性能。

除了应用程序的可移植性之外,WebAssembly 还可以充当服务器端的跨语言桥梁。不幸的是,我们还没有看到太多这样的情况,因为用于与操作系统通信的接口(Web Assembly System Interface,缩写为 WASI)和跨语言边界工作(Wasm 组件模型)仍在开发中,还没有尚未达到必要的成熟度水平。
 
3.插件系统
当大多数应用程序达到一定程度的成熟度时,它们需要允许最终用户进行扩展。从历史上看,应用程序已经达到了丰富的配置系统或构建复杂的 DSL,但这些总是被证明是非常痛苦的管理或迫使开发人员使用不熟悉的语言工作。
我们来看一个例子:在像 NGINX 这样的系统中配置请求过滤规则。为此,系统管理员必须以他们不熟悉的自定义配置语言以声明方式实现所需的逻辑。他们受制于 NGINX 设计者预期的匹配和过滤运算符类型,这通常严重限制了他们实现所需行为的能力。如果出现任何问题,由于缺乏可用的工具,调试可能会令人沮丧。
一些较新的应用程序选择了不同的方法:提供一组标准接口并嵌入 Wasm 运行时,并让最终用户提供实现所需自定义逻辑的 Wasm 二进制文件。这为最终用户提供了一个更加灵活和熟悉的界面:他们可以实现任意复杂的业务逻辑,并且可以使用他们选择的任何语言来实现。出于安全考虑,这在其他语言中是不可能的,但 Wasm 使它变得可行,因为运行时可以沙箱化用户提供的代码。
今天使用的几个例子:
  • Envoy 代理最初由 Lyft 开发,现在在整个行业中使用,它允许使用 Wasm 构建扩展并在运行时动态加载。建立在 Envoy 之上的 Istio 服务网格也紧随其后。
  • Redpanda 是 Kafka 的替代品,允许用户使用 Wasm 编写流内自定义数据转换
  • Open Policy Agent 允许使用 Wasm 定义策略
  • Minecraft 服务器Feather使用 WebAssembly 在沙箱中运行插件。

 
4. 嵌入式沙盒
将 WebAssembly 嵌入到其他应用程序中的想法在插件系统之外很有用。事实上,它可用于沙箱整个第三方库或为第一方代码构建安全层。
Firefox通过保护自己免受第三方库中的错误(例如用于拼写检查或图像解码的库)在这一领域处于领先地位。结合一个名为 RLBox 的工具,它提供了一个污染层,它们可以防止这些库中的漏洞,而无需求助于严格的进程隔离。对于 Firefox,他们甚至没有在最终版本中发布 Wasm 二进制文件。编译成 Wasm 然后转译成另一种语言的过程,再加上 RLBox,提供了他们需要的安全性。
这种方法可能会阻止一些严重的漏洞被利用。由于攻击者通常将多个漏洞链接在一起,因此此类中间安全层可能会非常宝贵。
 
5. 容器化
在一条经常被引用的推文中,Docker 创始人 Solomon Hykes 强调了 WebAssembly 的重要性:
如果 WASM+WASI 在 2008 年存在,我们就不需要创建 Docker。这就是它的重要性。服务器上的 Webassembly 是计算的未来。
有充分的理由相信 Wasm 代表了容器化的未来。与 Docker 相比,它的冷启动时间快了 10-100 倍,占用空间更小,并使用了更好的基于能力的约束安全模型。使 Wasm 模块(而不是容器)成为计算和部署的标准单元将实现更好的可扩展性和安全性。
这种转变不会在一夜之间发生,因此基于 Wasm 的容器化可能会集成到现有的编排系统中,而不是试图完全取代 Docker。
我预计这个空间将在未来几年内充满活力。一些项目已经处于领先地位:
  • Microsoft Azure 的 Deis Labs 构建了 Krustlet,这是一种在现有 Kubernetes 集群中运行 Wasm 工作负载的方法。
  • Deis Labs 还发布了Hippo,一个以 Wasm 为中心的平台即服务。我猜Fermyon正试图将这项技术商业化。
  • 通过他们的wasmCloud项目,Cosmonic正在构建一个平台和编排层,将 Wasm 容器化与分布式系统的参与者模型相结合。
  • Lunatic平台还包含 Actor 模型,并且似乎具有在单个 WebAssembly 运行时进程之上运行多个轻容器的最佳支持。
  • SuborbitalAtmo是另一个平台和编排系统,但更面向无服务器工作负载。

 
6. FaaS/无服务器平台
功能即服务平台需要快速安全地执行用户提供的代码。由于无服务器平台通常用于短时间运行代码,因此启动时间是一个特别重要的指标。超快的冷启动和广泛的语言支持使 Wasm 成为无服务器工作负载的理想选择。
Cloudflare WorkersFastly Compute@Edge提供的 CDN 边缘计算平台已经提供了运行 WebAssembly 的能力。Fastly 声称启动时间比市场上的其他产品快 100 倍,并将这种加速归功于他们基于 WebAssembly 的编译器和运行时。Netlify 和 Vercel 也在这个领域构建产品。
主要云提供商构建的无服务器平台也不甘落后:AWS Lambda 几个月前推出了 WebAssembly 无服务器功能,我预计 GCP 和 Azure 也会效仿。
 
7.区块链
以太坊和 Solana 等平台为用户编写代码提供了一种机制,称为“智能合约”,可以在区块链上运行。以太坊构建了一个完全定制的系统,创建了一种名为 Solidity 的语言,一种用于编译字节码的二进制格式,以及用于沙盒执行的以太坊虚拟机。Solana 选择重用一些现有的创新,利用 LLVM 编译器基础架构将 C、C++ 或 Rust 代码编译为受伯克利包过滤器启发的二进制字节码格式,但仍然构建了自己的运行时,称为 Sealevel。
WebAssembly 已经提供了很多这样的基础设施:它允许用户用他们选择的语言编写代码,提供编译器基础设施来生成 Wasm 字节码,并具有许多高性能运行时。
但是如果以太坊和 Solana 已经构建了这个基础设施,那么 WebAssembly 提供了什么价值呢?主要的增值实际上是围绕生态系统。例如,以太坊有自己的智能合约编写语言,这意味着它无法利用其他语言编写的所有库和常用函数。Solana 好一点,因为它可以使用 Rust 生态系统。假设可以克服技术挑战,WebAssembly 向更广泛的受众开放智能合约开发,并使他们能够使用他们已经熟悉的库和工具。
我绝对不是第一个意识到这一点的人。例如,Polkadot 网络使用基于WebAssembly 的虚拟机作为其运行时。EOS 虚拟机也是基于 WebAssembly 的CosmWasm使用它来构建跨多个区块链工作的智能合约。还有一个名为eWASM的提议,用 WebAssembly 的有限子集取代以太坊虚拟机,但似乎这项努力已经失败了。Wasmer 运行时提供了一种明确为区块链构建的“单通道”编译器模式,而 WasmEdge 声称拥有与以太坊兼容的智能合约执行引擎。
 
预测和机会
1. 一种新的应用架构
正如 Docker 无法完全替代虚拟机一样,Wasm 也无法完全替代 Docker。例如,Docker 容器不能运行自定义操作系统内核,而虚拟机可以。同样,Wasm 容器不能使用一些专门的 CPU 指令,例如 x86 的 256 位 AVX 指令9,因此在某些应用程序的性能上无法与 Docker 竞争。
在我看来,Docker 可以支持但 Wasm 不能支持的工作负载集目前大于 Docker 和虚拟机之间的类似增量。然而,Wasm 仍然是一项发展中的技术,因此将逐渐能够处理更多类型的工作负载。Docker 的兴起与微服务架构的兴起密切相关。这采用了非常适合虚拟机的单体应用程序,并将其替换为非常适合 Docker 容器的微服务。我们可能会看到一种利用 WebAssembly 独特功能的新应用程序架构。
根据康威定律,应用程序的架构反映了产生它的组织的通信结构。计算历史上每一个新的“参考架构”都减少了人与人之间所需的协调量。从大型机到虚拟机再到 Docker 容器,生产可部署单元所需的人数逐渐减少。我们通过将系统分解成越来越小的组件并允许构建这些组件的人员独立于定义良好的接口工作来实现这一点。虽然微服务已经将单体应用程序分解成几个小的独立服务,但 WebAssembly 使将微服务分解成更小的组件变得更加容易。
这会是什么样子?这里有几种可能性:
  • 当您将应用程序拆分为核心业务逻辑和与其他系统一起工作所需的胶水代码时,事实证明,与其他系统相比,业务逻辑通常非常小。通过将胶水代码的接口与其提供的功能的实现分离,可以构建以业务逻辑为中心的应用程序并将其余部分委托给外部功能提供者。再加上长期靠边站的Actor模型,这就是wasmCloud做法的精髓。
  • 另一种可能性是,无服务器架构是超越微服务的下一步。大多数服务可以分为有状态和无状态部分,无状态部分可以作为任意可扩展的无服务器功能运行。在这种情况下,WebAssembly 为那些无服务器功能提供了方便且易于扩展的运行时。
  • WebAssembly 可能会改变我们处理第三方依赖项的方式。现代代码严重依赖第三方库,11并且这些依赖项中的大多数都没有经过全面或频繁的审查。随着最近的Log4j 漏洞等软件供应链问题的曝光,我预计人们将开始更加重视第三方库的安全性。像 Firefox 使用 Wasm 和 RLBox 来隔离某些库的方法将变得更加普遍。假设可以克服性能限制,将第三方库隔离到同一 Wasm 运行时内的单独功能受限容器中也是可行的。

 
2. 棕地部署
Wasm 最终将需要以某种方式与 Docker 进行互操作。在接下来的几年里,这并不是绝对必要的,因为 Wasm 将主要用于绿地部署,对向后兼容性的要求很少。但最终,Wasm 的棕地部署需要很容易才能完全赢得容器化竞赛,尤其是在企业环境中。
一个潜在的结果是 Docker 将集成 Wasm 运行时。虽然看似合理,但我预计 Wasm 将有足够的差异化,以保证完全独立的工具。相反,Docker 和 Wasm 容器的统一将发生在编排层。
Kubernetes 是否会有效地集成基于 Wasm 的执行,或者是否会出现新的编排系统,目前尚不清楚。一方面,Kubernetes 目前是无可匹敌的编排之王。它具有令人难以置信的势头,Wasm 集装箱化运动将是明智的选择。微软的人们正在通过构建Krustlet来投资这个未来,它允许您在 Kubernetes 中运行 Wasm 工作负载。另一方面,Wasm 代码与 Docker 容器有不同的要求,因此 Kubernetes 可能不适合。例如,在使用基于 Wasm 的第三方库隔离时,为容器间通信设置共享内存会很有用,这在 Kubernetes 中很难做到。这样的 Wasm-native 编排器最终将构建桥梁,以简化从 Docker 迁移或与 Docker 的集成。
虽然我对即将到来的 Wasm 编排器浪潮充满希望,但 Kubernetes 已经足够稳固,短期内它可能不会有任何进展。
 
3. 标准化的无服务器/边缘框架
大多数无服务器提供商都有自己的框架来定义路由和 lambda 函数。例如,Cloudflare 定义了自己的“cf”类型,并提供了一个名为 wrangler 的 CLI 工具来设置代码脚手架。Fastly 有自己的一组接口用于与缓存和日志交互,AWS Lambda 也有类似的设置。Kubernetes 的 Fission 框架有自己的一组库,用于与各种语言集成。一些平台试图通过让用户提供 Docker 容器来规避这个问题,这样平台只需要处理执行。KnativeFly.io都遵循这种方法。然而,他们必须保持一个“暖池”的工作人员来减少冷启动时间的影响,或者将这个问题传递给他们的用户。
有机会构建标准化的无服务器功能定义和部署规范。流行的无服务器框架在抽象部署方面做得不错,但仍将特定于提供程序的细节泄漏到功能实现中。一旦这些细节被抽象出来,多云部署就变得更加容易,因此框架变得更加强大。它最终可能会像无服务器的 Terraform。
 
4. 包管理
每种编程语言都有一个围绕它的生态系统。大多数现代语言都有一个集中的包注册表:Python 有 PyPI,NodeJS 有 npm,Rust 有 Crates.io。此类注册表以及伴随它们的工具和工作流程对于开发高质量的生态系统非常重要,并使开发人员的生活更加轻松。
对于 Wasm,WebAssembly 包管理器(WAPM) 承诺填补这一空白。然而,在实践中,该项目似乎在很大程度上处于休眠状态。在撰写本文时,过去两个月只更新了三个包。问题是软件包应该相互构建,但 WAPM 仅适用于没有相互依赖关系的独立 Wasm 二进制文件。开发人员的另一个选择是将 Wasm 模块发布到 npm,但这当然不适合在 JavaScript 或 AssemblyScript 之外构建 Wasm 生态系统,因为它不鼓励跨语言互操作性。
这个问题实际上并不是 WAPM 或 npm 的错,而是 WebAssembly 本身的问题。

这正是 WebAssembly 组件模型要解决的问题。Wasm 组件标准化了 WebAssembly 接口格式,并为实现和使用这些接口提供了代码生成器。换句话说,它让我们可以使用 Wasm 轻松跨越运行时和语言边界。
为 WebAssembly 构建一个高质量的包管理器是一个很大的机会。它应该使用 Wasm 组件 codegen 来生成使用其他语言的 Wasm 模块的绑定。如果工具足够好,它可以使跨语言开发变得轻而易举,这将是服务器端 WebAssembly 生态系统的真正解锁。Wasm 包注册表甚至可以跨其他包注册表联合,自动发布具有适当生成绑定到 PyPI、npm 和 Crates.io 的包。
 
结论
此时你可能在想:如果 WebAssembly 这么好,为什么没有得到更广泛的使用?让我自愿做出一些回应:

  • WebAssembly 的营销并不好。这个名字用词不当,因为它既不限于网络也不是汇编。WebAssembly 主要面向 Web 开发人员进行营销和推广,但其真正的潜力在于浏览器之外。当 C++ 和 Rust 开发人员集体开始认识到 Wasm 所拥有的潜力时,真正的解锁将会到来。
  • WebAssembly 标准化还不存在。例如,WebAssembly 系统接口有许多尚未正式标准化的扩展,但各种运行时实现了这些扩展的选择。普遍可移植性的承诺尚未完全实现。
  • 跨语言交互很糟糕。在人们真正开始跨不同语言使用 Wasm 之前,我们需要 WebAssembly 组件和优秀的代码生成器来支持大量语言。
  • 开发人员的体验还有很多不足之处。我希望看到工具方面的改进,尤其是在调试方面,以及与包管理器、构建系统和 IDE 的集成。
  • 我不想这么说,但在 WebAssembly 的库隔离功能得到充分认可之前,我们可能需要一些更严重的软件供应链事件,其规模与 Log4Shell 相似。

WebAssembly 已经部署在相当多的地方,并服务于各种各样的用例,但这些代表了更广泛的科技世界中孤立的活动领域。在我的朋友中,听说过 WebAssembly 的一小部分人认为它在原则上非常令人兴奋,但由于它还不够成熟,所以没有使用它进行构建。但是,其中许多问题正在积极处理中,并且可能会在未来一两年内达到可接受的状态。因此,我们似乎正处于 WebAssembly 活动、生态系统和社区爆发的边缘。