超越浏览器:无服务器 WebAssembly 入门

已发表: 2022-03-10
快速总结↬你可能听说过 WebAssembly 以及为什么它是浏览器中的强大工具。 在本文中,我们探讨了为什么无服务器 WebAssembly 在浏览器之外可能同样强大,以及如何开始使用它。

现在所有主要浏览器和全球 85% 以上的用户都支持 WebAssembly,JavaScript 不再是唯一的浏览器语言。 如果你没有听说过,WebAssembly 是一种在浏览器中运行的新的低级语言。 它也是一个编译目标,这意味着您可以将用 C、C++ 和 Rust 等语言编写的现有程序编译成 WebAssembly,并在浏览器中运行这些程序。 到目前为止,WebAssembly 已被用于将各种应用程序移植到 Web,包括桌面应用程序、命令行工具、游戏和数据科学工具。

注意:有关如何在浏览器中使用 WebAssembly 来加速 Web 应用程序的深入案例研究,请查看我之前的文章。

WebAssembly 在 Web 之外?

尽管当今大多数 WebAssembly 应用程序都是以浏览器为中心的,但 WebAssembly 本身最初并不是为 Web 设计的,而是真正为任何沙盒环境设计的。 事实上,最近有很多兴趣探索 WebAssembly 如何在浏览器之外发挥作用,作为在任何操作系统或计算机架构上运行二进制文件的通用方法,只要有支持该系统的 WebAssembly 运行时。 在本文中,我们将了解如何以无服务器/功能即服务 (FaaS) 方式在浏览器之外运行 WebAssembly。

跳跃后更多! 继续往下看↓

用于无服务器应用程序的 WebAssembly

简而言之,无服务器函数是一种计算模型,您将代码交给云提供商,让他们为您执行和管理代码扩展。 例如,您可以要求在您调用 API 端点时执行无服务器函数,或者由事件驱动,例如文件上传到云存储桶时。 虽然术语“无服务器”可能看起来用词不当,因为服务器显然在此过程中涉及到某个地方,但从我们的角度来看,它是无服务器的,因为我们不需要担心如何管理、部署或扩展这些服务器。

尽管这些函数通常是用 Python 和 JavaScript (Node.js) 等语言编写的,但您可能选择使用 WebAssembly 的原因有很多:

  1. 更快的初始化时间
    支持 WebAssembly 的无服务器提供商(包括 Cloudflare 和 Fastly 报告说,他们启动功能的速度至少比大多数云提供商使用其他语言的速度快一个数量级。他们通过在同一进程中运行数万个 WebAssembly 模块来实现这一点,即之所以可能,是因为 WebAssembly 的沙盒特性提供了一种更有效的方式来获得容器传统上使用的隔离。
  2. 无需重写
    WebAssembly 在浏览器中的主要吸引力之一是能够将现有代码移植到 Web,而无需将所有内容重写为 JavaScript。 这种优势在无服务器用例中仍然适用,因为云提供商限制了您可以使用哪些语言编写无服务器函数。通常,它们将支持 Python、Node.js 以及其他一些,但肯定不支持 C、C++ 或 Rust . 通过支持 WebAssembly,无服务器提供商可以间接支持更多的语言。
  3. 更轻量级
    在浏览器中运行 WebAssembly 时,我们依赖最终用户的计算机来执行我们的计算。 如果这些计算过于密集,我们的用户会在他们的电脑风扇开始嗡嗡作响时不高兴。 在浏览器之外运行 WebAssembly 为我们提供了 WebAssembly 的速度和可移植性优势,同时还保持了我们的应用程序的轻量级。 最重要的是,由于我们在更可预测的环境中运行我们的 WebAssembly 代码,我们可以潜在地执行更密集的计算。

一个具体的例子

在我之前在 Smashing Magazine 上的文章中,我们讨论了如何通过将慢速 JavaScript 计算替换为编译为 WebAssembly 的 C 代码来加速 Web 应用程序。 有问题的网络应用程序是 fastq.bio,这是一个预览 DNA 测序数据质量的工具。

作为一个具体的例子,让我们将 fastq.bio 重写为一个使用无服务器 WebAssembly 的应用程序,而不是在浏览器中运行 WebAssembly。 在本文中,我们将使用 Cloudflare Workers,这是一个支持 WebAssembly 并构建在 V8 浏览器引擎之上的无服务器提供商。 另一家云提供商 Fastly 正在开发类似的产品,但基于他们的 Lucet 运行时。

首先,让我们编写一些 Rust 代码来分析 DNA 测序数据的数据质量。 为方便起见,我们可以利用 Rust-Bio 生物信息学库来处理输入数据的解析,并利用 wasm-bindgen 库来帮助我们将 Rust 代码编译为 WebAssembly。

这是读取 DNA 测序数据并输出带有质量指标摘要的 JSON 的代码片段:

 // Import packages extern crate wasm_bindgen; use bio::seq_analysis::gc; use bio::io::fastq; ... // This "wasm_bindgen" tag lets us denote the functions // we want to expose in our WebAssembly module #[wasm_bindgen] pub fn fastq_metrics(seq: String) -> String { ... // Loop through lines in the file let reader = fastq::Reader::new(seq.as_bytes()); for result in reader.records() { let record = result.unwrap(); let sequence = record.seq(); // Calculate simple statistics on each record n_reads += 1.0; let read_length = sequence.len(); let read_gc = gc::gc_content(sequence); // We want to draw histograms of these values // so we store their values for later plotting hist_gc.push(read_gc * 100.0); hist_len.push(read_length); ... } // Return statistics as a JSON blob json!({ "n": n_reads, "hist": { "gc": hist_gc, "len": hist_len }, ... }).to_string() }

然后,我们使用 Cloudflare 的 wrangler 命令行工具来完成编译到 WebAssembly 和部署到云的繁重工作。 完成后,我们将获得一个 API 端点,该端点将排序数据作为输入并返回带有数据质量指标的 JSON。 我们现在可以将该 API 集成到我们的应用程序中。

这是应用程序的 GIF 动图:

我们的应用程序并行调用无服务器 WebAssembly 函数并使用它返回的数据更新绘图的 GIF。
我们的应用程序的无服务器版本不是直接在浏览器中运行分析,而是向我们的无服务器函数发出多个 POST 请求(见右侧栏),并在每次返回更多数据时更新绘图。 (大预览)

完整代码可在 GitHub(开源)上获得。

把它放在上下文中

为了将无服务器 WebAssembly 方法放在上下文中,让我们考虑构建数据处理 Web 应用程序(即我们对用户提供的数据执行分析的 Web 应用程序)的四种主要方式:

此图显示了我们可以在 Web 应用程序中构建数据处理的四种方式:在服务器上(不使用 WebAssembly)、在使用 JavaScript 的浏览器中、在使用 WebAssembly 的浏览器中和无服务器 WebAssembly。
我们可以为处理数据的应用程序采取四种不同的架构选择。 (大预览)

如上图,数据处理可以在几个地方进行:

  1. 服务器端
    这是大多数 Web 应用程序采用的方法,在前端进行的 API 调用在后端启动数据处理。
  2. 客户端 JavaScript
    在这种方法中,数据处理代码用 JavaScript 编写并在浏览器中运行。 缺点是你的性能会受到影响,如果你的原始代码不是用 JavaScript 编写的,你需要从头开始重写它!
  3. 客户端 WebAssembly
    这涉及将数据分析代码编译为 WebAssembly 并在浏览器中运行。 如果分析代码是用 C、C++ 或 Rust 等语言编写的(这在我的基因组学领域很常见),那么就不需要用 JavaScript 重写复杂的算法。 它还提供了加速我们的应用程序的潜力(例如,如前一篇文章中所讨论的)。
  4. 无服务器 WebAssembly
    这涉及使用 FaaS 类型的模型(例如本文)在云上运行已编译的 WebAssembly。

那么,为什么您会选择无服务器方法而不是其他方法呢? 一方面,与第一种方法相比,它具有使用 WebAssembly 带来的好处,尤其是能够移植现有代码而无需将其重写为 JavaScript。 与第三种方法相比,无服务器 WebAssembly 还意味着我们的应用程序更轻量级,因为我们不使用用户的资源进行数字运算。 特别是,如果计算相当复杂,或者数据已经在云中,这种方法更有意义。

但是,另一方面,应用程序现在需要建立网络连接,因此应用程序可能会变慢。 此外,根据计算的规模以及是否可以将其分解为更小的分析块,由于无服务器云提供商对运行时、CPU 和 RAM 利用率的限制,这种方法可能不适合。

结论

正如我们所看到的,现在可以以无服务器方式运行 WebAssembly 代码,并获得 WebAssembly(可移植性和速度)和功能即服务架构(自动扩展和按使用定价)的优势)。 某些类型的应用程序(例如数据分析和图像处理等)可以从这种方法中受益匪浅。 虽然运行时会因为额外的网络往返而受到影响,但这种方法确实允许我们一次处理更多数据,而不会消耗用户的资源。