Language:Chinese VersionEnglish Version

多年来,WebAssembly 一直与浏览器划等号。这项技术让你能在网页中以接近原生的速度运行 C++ 游戏、Photoshop 和 Python 解释器。但现在,Wasm 生态系统最重要的发展完全发生在浏览器之外。服务器端 WebAssembly 正在成为特定工作负载下容器的合法替代方案——更轻量、启动更快、默认更安全,并且真正能够跨架构和操作系统移植。

到 2026 年,服务器端 Wasm 已不再是一个研究项目。它正在从初创公司到云服务提供商的各种公司生产环境中运行,支持从边缘函数到插件系统再到完整微服务的各种应用。本文探讨了服务器端 Wasm 的现状、其吸引人的优势以及仍存在的不足。

为什么要在浏览器外使用 Wasm

使 WebAssembly 在浏览器中有价值的特性直接适用于服务器端用例。Wasm 模块默认是沙箱化的——除非明确授予权限,否则它们无法访问文件系统、网络或环境变量。它们是可移植的——在 macOS 上编译的模块在 Linux、Windows 和 ARM 上运行时完全相同。它们的启动时间是微秒级,而不是容器冷启动所需的秒级或分钟级。而且它们体积小——典型的 Wasm 模块以千字节计量,而不是容器图像常见的数百兆字节。

这些特性解决了服务器计算中的实际痛点。容器冷启动是无服务器平台的持续挑战。容器图像因仅用于兼容性的操作系统依赖而臃肿不堪。而容器安全模型需要复杂的运行时配置才能实现有意义的隔离——而这些配置经常被错误配置。

“如果 WASM+WASI 在 2008 年就存在,我们就不需要创建 Docker 了。” —— Docker 联合创始人 Solomon Hykes

这句 2019 年的引言在当时颇具争议性。到 2026 年,它看起来越来越具有预见性——不是预测 Wasm 会取代 Docker,而是认识到 Wasm 以一种更轻量的机制解决了 Docker 所解决的便携性和隔离问题。

WASI 和组件模型

使服务器端 Wasm 成为可能的关键技术是 WASI —— WebAssembly 系统接口。WASI 提供了一套标准化的 API,允许 Wasm 模块与外界交互:读取文件、建立网络连接、访问环境变量,以及使用时钟和随机数生成器。

WASI Preview 2

WASI Preview 2 于 2024 年初最终确定,现已获得广泛支持,引入了组件模型——这是 Wasm 模块之间以及与宿主环境交互方式的一次重大演进。组件模型定义了一个类型系统和接口定义语言(WIT — Wasm 接口类型),使组件能够暴露和使用类型化接口。

// 示例 WIT 接口定义
package myapp:backend@1.0.0;

interface http-handler {
    record request {
        method: string,
        path: string,
        headers: list<tuple<string, string>>,
        body: option<list<u8>>,
    }

    record response {
        status: u16,
        headers: list<tuple<string, string>>,
        body: option<list<u8>>,
    }

    handle: func(req: request) -> response;
}

world backend {
    export http-handler;
    import wasi:logging/logging;
    import wasi:keyvalue/store;
}

组件模型正是将 Wasm 从二进制格式转变为真正的软件组件系统的关键。组件可以组合在一起——就像乐高积木一样——无论它们是用什么语言编写的。一个 Rust HTTP 处理器可以调用一个使用 Python ML 推理组件的 Go 认证模块,所有这些都在单个 Wasm 应用程序中实现。

WASI 目前提供什么

当前的 WASI 生态系统包括用于文件系统访问、HTTP 客户端和服务器操作、键值存储、Blob 存储、消息传递和 pub/sub、日志记录、随机数生成、时钟和计时器以及套接字的标准化接口。每个接口都在 WIT 中定义,可以由任何运行时实现。

运行时选项

多个生产级 Wasm 运行时竞相争夺服务器端工作负载,每种都有不同的优势。

Wasmtime

Wasmtime 由字节码联盟(包括 Mozilla、Fastly、Intel 和 Microsoft)开发,是 WASI 的参考实现。它优先考虑正确性、安全性和标准合规性。Wasmtime 使用 Cranelift——一个专门为 Wasm 设计的代码生成器——来生成高质量的本地代码。它提供提前编译和即时编译两种模式。

对于正确性和安全性至关重要的应用程序,Wasmtime 是最安全的选择。它的启动时间以微秒为单位测量,每个实例的内存开销最小——您可以在单个服务器上运行数千个隔离的 Wasm 实例。

WasmEdge

WasmEdge 专注于边缘和 AI 工作负载。它包含对 TensorFlow 和 PyTorch 推理的原生支持,使其特别适合在边缘运行 ML 模型。WasmEdge 还支持超出标准 WASI 接口的网络扩展、异步 I/O 和数据库连接器。

WasmEdge 在 Kubernetes 生态系统中特别受欢迎,在那里它作为针对特定工作负载运行完整容器的轻量级替代方案。CNCF(云原生计算基金会)将 WasmEdge 采纳为沙盒项目,这表明云原生社区对 Wasm 的兴趣。

Spin

Spin 由 Fermyon 公司开发,既是一个运行时也是一个开发者框架。与通用型 Wasm 运行时不同,Spin 专门用于构建基于 Wasm 的微服务和无服务器函数。它提供了接近传统 Web 框架的开发者体验,同时利用 Wasm 进行执行。

// Spin HTTP handler in Rust
use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::http_component;
use spin_sdk::key_value::Store;

#[http_component]
fn handle_request(req: Request) -> anyhow::Result<impl IntoResponse> {
    let store = Store::open_default()?;
    let path = req.path();

    match req.method() {
        Method::Get => {
            let value = store.get(path)?;
            match value {
                Some(v) => Ok(Response::builder()
                    .status(200)
                    .header("content-type", "application/json")
                    .body(v)
                    .build()),
                None => Ok(Response::builder()
                    .status(404)
                    .body("Not found")
                    .build()),
            }
        }
        _ => Ok(Response::builder()
            .status(405)
            .body("Method not allowed")
            .build()),
    }
}

基于 Wasm 的无服务器计算

无服务器计算模式是 Wasm 优势最显著的领域。传统的无服务器平台(AWS Lambda、Google Cloud Functions)存在数百毫秒到秒级的冷启动延迟。Wasm 函数的启动时间在微秒级别——这种差异对于延迟敏感的应用来说是革命性的。

Fermyon Cloud

Fermyon Cloud 是一个完全基于 Spin 和 Wasm 构建的无服务器平台。应用程序可在几秒内部署,在微秒内启动,并且仅消耗基于容器的替代方案所需资源的一小部分。Fermyon 报告称冷启动时间不到一毫秒——比传统无服务器平台快约 1000 倍。

Fastly Compute

Fastly 是最早采用服务器端 Wasm 的公司之一,用它来支持其边缘计算平台。Fastly Compute 在全球边缘位置运行 Wasm 模块,其启动时间能够实现按请求隔离——每个传入请求都可以启动一个全新的、隔离的 Wasm 实例,而不会产生有意义的开销。

这种按请求隔离模型比大多数边缘计算平台使用的共享进程模型要强大得多。一个请求处理程序中的漏洞不会影响其他请求,因为它们在完全独立的沙盒中运行。

Cloudflare Workers

Cloudflare Workers 同时支持 Wasm 和 JavaScript,允许开发者将性能关键组件部署为 Wasm 模块。JavaScript 使用 V8 隔离环境,而计算密集型任务使用 Wasm 的组合已被证明对于需要开发者友好性和原始性能的边缘应用是有效的。

插件系统

服务器端 Wasm 最有说服力的用例之一是构建插件系统。Wasm 为插件系统提供了三重优势:性能(接近原生执行)、安全性(默认沙箱隔离)和可移植性(任何语言都可以编译为 Wasm)。

Shopify(用于店面扩展)、Envoy Proxy(用于自定义过滤器)和 Zed(用于编辑器扩展)这样的公司使用 Wasm 来允许第三方代码扩展其平台,而不会危及主机应用的稳定性或安全性。

// 主应用程序加载 Wasm 插件(使用 Wasmtime 的 Rust)
use wasmtime::*;

fn load_plugin(engine: &Engine, plugin_path: &str) -> Result<Instance> {
    let module = Module::from_file(engine, plugin_path)?;
    let mut store = Store::new(engine, ());

    // 定义插件可以访问的内容
    let mut linker = Linker::new(engine);

    // 授予日志访问权限,但不授予文件系统或网络访问权限
    linker.func_wrap("env", "log", |msg: i32, len: i32| {
        // 安全的日志实现
    })?;

    // 授予带命名空间键值存储的访问权限
    linker.func_wrap("env", "kv_get", |key: i32, key_len: i32| -> i64 {
        // 命名空间键值访问
        0
    })?;

    let instance = linker.instantiate(&mut store, &module)?;
    Ok(instance)
}

安全特性非常适合此用例。尝试访问文件系统的插件会收到错误——不是因为运行时检查,而是因为从未授予该能力。这是最纯粹的能力安全:代码只能执行已被明确授予许可的操作。

多语言开发

组件模型实现了真正的多语言开发——不是指不同服务恰好使用不同语言的那种,而是指用不同语言编写的组件可以在单个应用程序内组合。团队可以用 Rust 编写 HTTP 处理代码以获得高性能,用 Go 编写业务逻辑以提高生产力,用 Python 编写数据转换代码以访问生态系统,所有三个组件在单个 Wasm 应用程序中一起运行。

编译到 Wasm 的语言支持已显著扩展。Rust 和 C/C++ 从一开始就拥有出色的支持。Go 在 1.21 版本中引入了原生的 Wasm/WASI 支持。Python 通过编译成 Wasm 的 CPython 运行(通过 Componentize-py 等项目)。JavaScript 和 TypeScript 通过 StarlingMonkey 等引擎编译。C# 通过 .NET 运行时针对 Wasm。甚至 Swift 和 Kotlin 等语言也在添加 Wasm 目标。

性能:Wasm 与容器

性能基准测试 consistently 显示,Wasm 在特定维度具有优势,而在其他方面则有所权衡。

启动时间: Wasm 明显胜出。Wasm 模块的冷启动时间通常不到 1 毫秒,而容器则需要 100 毫秒到几秒。对于无服务器和边缘计算,这种差异是革命性的。

内存占用: 每个 Wasm 实例消耗的内存要少得多。在单台服务器上运行 10,000 个隔离的 Wasm 实例是可行的。运行 10,000 个容器则不可行。

稳态吞吐量: 对于计算密集型工作负载,Wasm 的运行速度能达到原生速度的 80% 到 95%。运行原生二进制文件的容器将匹配原生速度。对于大多数工作负载,这种差异可以忽略不计。但对于最敏感性能的应用程序,这很重要。

I/O 性能: Wasm I/O 通过 WASI 抽象层,与直接系统调用相比增加了一点开销。对于 I/O 密集型工作负载,这种开销通常不到 5%。

镜像大小: 一个典型 Web 服务的 Wasm 模块为 1-10 MB。等效的容器镜像为 50-500 MB。这会影响部署速度、存储成本和网络带宽——特别是在边缘。

实际生产用例

服务器端 Wasm 并非理论概念。以下是具体的生产部署:

Fastly 通过由 Wasm 驱动的边缘函数每天处理数十亿请求。他们的整个计算平台都在 Wasmtime 上运行。

Shopify 将商家提供的店面扩展作为 Wasm 模块运行,为数百万在线商店提供服务,同时让不受信任的第三方代码在沙箱中安全运行。

Figma 使用 Wasm 构建其插件系统,允许设计师使用任何编译成 Wasm 的语言编写的自定义工具来扩展平台。

SingleStore 允许用户用任何语言编写数据库 UDF(用户定义函数),编译成 Wasm 并在数据库引擎内执行。

Fermyon 在 Spin 上运行自己的平台,证明 Wasm 不仅可以驱动边缘函数,还可以支持这些函数所依赖的基础设施。

Wasm 目前还不是什么

尽管前景广阔,服务器端 Wasm 仍有实际限制,使其无法完全取代容器。

线程处理: Wasm 线程支持仍在成熟中。依赖共享内存多线程的 CPU 并行工作负载更适合通过运行原生二进制文件的容器来提供服务。

生态系统成熟度: Wasm 的库生态系统正在增长但不完整。许多流行的库具有无法编译为 Wasm 的依赖项——原生扩展、平台特定代码以及缺乏 WASI 实现的系统库。

调试: 调试 Wasm 应用程序比调试原生应用程序更困难。源映射和调试信息支持正在改进,但尚未达到原生工具链的水平。

网络: 虽然 WASI 提供了套接字和 HTTP 接口,但其网络模型比容器所提供的更为受限。需要原始套接字访问或复杂网络配置的应用程序可能会发现 Wasm 的局限性。

前进之路

2026 年的服务器端 WebAssembly 处于类似于 2014 年容器的位置——对于特定用例具有明确价值,正在快速改进,并朝着更广泛采用的方向发展。它不会取代所有工作负载的容器。它将成为边缘计算、无服务器函数、插件系统以及任何将启动时间、隔离性和便携性作为主要关注点的用例的默认选择。

组件模型是值得关注的关键技术。随着它的成熟和工具的改进,从语言无关组件组合软件的能力将改变我们构建和分发软件的方式。浏览器为 Wasm 提供了起点,而服务器则是它将发挥全部潜力的地方。

By Michael Sun

Founder and Editor-in-Chief of NovVista. Software engineer with hands-on experience in cloud infrastructure, full-stack development, and DevOps. Writes about AI tools, developer workflows, server architecture, and the practical side of technology. Based in China.

Leave a Reply

Your email address will not be published. Required fields are marked *

You missed