news 2026/4/30 21:27:35

用 Rust 写 Serverless:Cloudflare Workers + WebAssembly 实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用 Rust 写 Serverless:Cloudflare Workers + WebAssembly 实践

背景

Cloudflare Workers 是 Cloudflare 提供的 Serverless 运行平台,代码运行在全球 150+ 个数据中心的边缘节点上。它原生支持 JavaScript,而随着 WebAssembly(WASM)支持的加入,Rust 开发者也可以把自己的代码编译成 WASM,部署到这套平台上运行。

这篇文章以一个实际项目为例,介绍如何把 Rust 代码编译为 WASM,先在本地浏览器中跑通,再上传到 Workers 作为 Serverless 函数对外提供服务。

原文地址:https://blog.cloudflare.com/cloudflare-workers-as-a-serverless-rust-platform/


什么时候适合用 WASM

在开始之前,有一点需要明确:WASM 不是万能的。

Cloudflare 官方文档中有一段很务实的说法:对于轻量任务,比如做一次请求重定向、校验一个 Token,纯 JavaScript 往往比 WASM 更快、更简单。原因在于 WASM 运行在独立的内存空间里,数据进出都需要拷贝,如果代码本身没有密集的计算,引入 WASM 反而会带来额外开销。

WASM 真正发挥优势的场景是计算密集型任务:图像处理、加解密、复杂的字符串操作等。


环境搭建

Rust 的 WASM 工具链目前已经相当成熟,核心工具是wasm-pack

# 安装 wasm-packcurlhttps://rustwasm.github.io/wasm-pack/installer/init.sh-sSf|sh# 安装 cargo-generate,用于基于模板创建项目cargoinstallcargo-generate# 用官方模板创建一个新项目cargogenerate--githttps://github.com/rustwasm/wasm-pack-template

wasm-pack的作用是把 Rust 代码编译成 WebAssembly,同时生成 JavaScript 和 Rust 之间的类型绑定(binding)。这个绑定层很关键,后面会详细说。


代码结构:#[wasm_bindgen]

模板项目的核心模式是这样的:

#[wasm_bindgen]extern{fnalert(s:&str);}#[wasm_bindgen]pubfngreet(){alert("Hello from Rust!");}

这里做了两件事:

第一,通过extern块声明外部函数——也就是宿主环境(浏览器或 Workers)提供的函数,比如alert

第二,用#[wasm_bindgen]标注的pub fn,会被暴露出去,让 JavaScript 侧可以直接调用,就像调用普通 JS 函数一样。

编译命令:

wasm-pack build

编译产物在pkg/目录下,包含.wasm二进制文件和自动生成的 JS 胶水代码。


本地验证

编译完成后,先不急着上线,在本地浏览器里跑通是个好习惯。

npm 上有一个create-wasm-app模板,提供了一个预配置好 webpack 的测试页面,可以直接 import WASM 模块:

npminit wasm-app wwwcdwwwnpminstallnpmstart

浏览器访问http://localhost:8080,如果看到页面正常渲染,说明 WASM 模块加载成功。

把自己的 wasm 包用npm link关联进来,修改www/index.js,调用自己的函数:

import*aswasmfrom"my-wasm-module";letresult=wasm.get_phrase_text(100,10);console.log(result);

一个坑:系统调用在 WASM 里不可用

作者在实际开发中踩了一个典型的坑:用 Rust 的随机数库SmallRng::from_entropy()时,本地cargo test完全正常,但在浏览器里跑 WASM 时直接崩溃。

原因是from_entropy()底层依赖系统调用来获取熵值,而 WASM 的编译目标是wasm32-unknown-unknown——这个unknown意味着目标平台不保证提供任何系统调用。编译器不报错,但运行时会直接失败。

解决方案是换掉系统级调用,改用 JavaScript 宿主提供的 Web API。Rust 有一个js-syscrate,封装了标准 ECMAScript 提供的所有全局对象,其中包括Date

fnget_rng()->SmallRng{usejs_sys::Date;userand::SeedableRng;letticks=Date::now();lettick_bytes=transmute(ticksasu128);SmallRng::from_seed(tick_bytes)}

Date.now()作为种子,绕开了系统调用,问题解决。

这个经验值得记住:在 WASM 环境下,任何涉及 I/O、系统熵、文件系统、时间获取的操作,都需要通过宿主环境(JS)来代理,不能直接走 Rust 标准库的对应实现。


上传到 Workers

本地浏览器跑通之后,接下来把.wasm文件上传到 Cloudflare Workers。

上传时把 WASM 绑定到一个全局变量(比如BOBROSS_WASM),Workers 运行时会在 Worker 脚本启动时自动实例化这个模块。

但这里有一个需要手动处理的地方:wasm-pack build生成的 JS 胶水代码是为浏览器环境写的(使用了 ES module 的import/export语法),Workers 的 WASM 实例化方式和浏览器略有不同,需要做几处改造:

  • 删除顶部的import语句
  • 去掉函数的export关键字
  • 把所有函数包进一个模块对象
  • 构造importObject,把需要注入的外部函数传进去
  • 在创建WebAssembly.Instance时传入这个importObject

改造完成后,在 Worker 脚本里调用 Rust 函数的方式和调用普通 JavaScript 函数没有区别:

asyncfunctionhandleRequest(request){leturl=newURL(request.url);letphraseCount=parseInt(url.searchParams.get("phrases")||100);letnewLine=parseInt(url.searchParams.get("newline")||0);// 调用 Rust 编译的 WASM 函数letphraseText=mod.get_phrase_text(phraseCount,newLine);returnnewResponse(phraseText);}

请求进来,Rust 函数被调用,结果直接返回——运行在全球 150+ 个边缘节点上。


整体流程回顾

Rust 源码 ↓ wasm-pack build .wasm 二进制 + JS 胶水代码 ↓ 本地 npm link + webpack 测试页 浏览器验证通过 ↓ 手动改造 JS 胶水代码(适配 Workers) 上传 .wasm + Worker 脚本到 Cloudflare ↓ 全球边缘节点运行

小结

这篇博客展示的是一条完整的路径:Rust 代码 → WASM → Cloudflare Workers。整个工具链在当时(2018年)还比较初期,需要手动处理 JS 胶水代码的适配。现在 Cloudflare 已经提供了 Wrangler CLI,把这些工作都封装进去了,流程更加顺滑。

几个值得关注的核心点:

WASM 不是银弹,轻量逻辑用 JS 就好,WASM 适合计算密集型场景。

系统调用在 WASM 里不可用,需要通过js-sys等工具桥接宿主环境的 Web API。

胶水代码是关键中间层wasm-bindgen自动处理了 JS 和 Rust 之间的类型转换和内存管理,理解它的工作方式对排查问题很有帮助。

Serverless + Rust + WASM 这条路是通的,而且随着工具链的持续完善,门槛在逐步降低。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/30 21:26:25

开始做 GEO 前,先想清哪些问题?一文讲清判断框架

做 GEO 之前,先不要把问题拆成“发多少内容”“监测哪些平台”“要不要做一批问答页”。 这些都是后面的动作。第一层要先确认:你要优化的对象到底是什么。 放到企业起步里,GEO 可以先理解成一句话:让 AI 在客户真实问题里&#x…

作者头像 李华
网站建设 2026/4/30 21:16:26

用QT和C++从零搭建一个离线信号分析工具:我的半年踩坑与实战心得

用QT和C从零搭建一个离线信号分析工具:我的半年踩坑与实战心得 第一次打开QT Creator时,我完全没料到这个看似简单的信号分析项目会让我在接下来六个月里反复推翻重来。作为一个常年与MATLAB打交道的算法工程师,这次要用C实现带GUI的完整信号…

作者头像 李华
网站建设 2026/4/30 21:15:02

为 hermes agent 配置 taotoken 作为自定义模型供应商

为 Hermes Agent 配置 Taotoken 作为自定义模型供应商 1. 准备工作 在开始配置前,请确保已安装 Hermes Agent 并具备基本运行环境。同时需要准备好 Taotoken 的 API Key,该 Key 可在 Taotoken 控制台的「API 密钥」页面创建。模型 ID 可在「模型广场」…

作者头像 李华
网站建设 2026/4/30 21:14:01

EPO算法优化LLM智能体的强化学习实践

1. EPO算法与LLM智能体的技术背景EPO(Evolutionary Policy Optimization)算法是近年来强化学习领域兴起的一种新型优化方法,它结合了进化算法和策略梯度的优势。与传统PPO(Proximal Policy Optimization)相比&#xff…

作者头像 李华