虽然 Cloudflare Workers 的行为与浏览器或 Node.js 中的 JavaScript ↗ 类似,但在编写代码时仍需考虑一些差异。Workers 运行时在底层使用 V8 引擎 ↗——与 Chromium 和 Node.js 使用的引擎相同。Workers 运行时还实现了大多数现代浏览器中可用的许多标准 API。
为浏览器或 Node.js 编写的 JavaScript 与 Workers 之间的差异体现在运行时。Workers 函数并非运行在单台机器上(例如浏览器应用或集中式服务器 ↗),而是运行在 Cloudflare 全球网络 ↗上——一个不断扩展的全球网络,由分布在数百个位置的数千台机器组成。
这些机器中的每一台都托管 Workers 运行时实例,而每个运行时都能运行数千个用户定义的应用。本指南将介绍其中一些差异。
如需更多信息,请参阅 Cloud Computing without Containers 博客文章 ↗。
最大的三个差异是:Isolates、按请求计算(Compute per Request)和分布式执行(Distributed Execution)。
V8 ↗ 编排 isolates:轻量级上下文,为代码提供可访问的变量以及安全执行环境。您可以将 isolate 视为函数运行的沙箱。
运行时的单个实例可以运行数百或数千个 isolate,在它们之间无缝切换。每个 isolate 的内存完全隔离,因此每段代码都受到运行时中其他不受信任或用户编写代码的保护。Isolate 还设计为快速启动。与为每个函数创建虚拟机不同,isolate 是在现有环境中创建的。此模型消除了虚拟机模型的冷启动。与使用容器化进程 ↗(每个进程运行一个语言运行时实例)的其他无服务器提供商不同,Workers 在容器启动时只需支付一次 JavaScript 运行时的开销。Workers 进程能够运行几乎无限数量的脚本,几乎没有单独的开销。任何给定的 isolate 启动速度比容器或虚拟机上的 Node 进程快约一百倍。值得注意的是,启动时 isolate 消耗的内存少一个数量级。
给定 isolate 有自己的作用域,但 isolate 不一定长期存在。isolate 可能因多种原因被关闭并驱逐:
- 机器上的资源限制。
- 可疑脚本——任何试图突破 isolate 沙箱的行为。
- 个别资源限制。
因此,通常建议不要在全局作用域中存储可变状态,除非您已考虑到这种可能性。
如果您想了解 Cloudflare 如何在 Workers 运行时中处理安全,可以阅读 Isolates 与安全及 Spectre 威胁缓解的关系。
大多数 Worker 都是默认 Workers 流程的变体:
export default {
async fetch(request, env, ctx) {
return new Response('Hello World!');
},
};export default {
async fetch(request, env, ctx): Promise<Response> {
return new Response('Hello World!');
},
} satisfies ExportedHandler<Env>;对于使用 ES modules 语法 编写的 Worker,当 Cloudflare 任一数据中心收到对你的 *.workers.dev 子域或 Cloudflare 托管域的请求时,该请求会使用给定请求调用 Worker 代码中定义的 fetch() handler。你可以通过返回 Response 对象来响应请求。
Isolates 在请求持续期间具有弹性且持续可用,但在极少数情况下 isolate 可能被驱逐。当 Worker 达到官方限制,或运行请求的机器上资源异常紧张时,运行时会在事件正确解析后选择性地驱逐 isolates。
与所有其他 JavaScript 平台一样,单个 Workers 实例可以处理多个请求,包括单线程事件循环中的并发请求。这意味着在处理请求期间等待任何 async 任务(例如 fetch)时,如果有其他请求到达,可能会(也可能不会)处理这些请求。
由于无法保证任意两个用户请求会路由到 Worker 的相同或不同实例,Cloudflare 建议您不要使用或修改全局状态。
fetch()handler - 了解传入 Worker 的 HTTP 请求如何传递给fetch()handler。- Request - 了解传入的 HTTP 请求如何传递给
fetch()handler。 - Workers limits - 了解 Workers 限制,包括 Worker 大小、启动时间等。