Cloudflare Workers 简介
2018 年,Cloudflare 发布了 Cloudflare Workers (CFW),这是一个基于 V8 和Service Workers API 标准的 FaaS 平台。那一年,我写了一篇关于这个话题的小文章,但是并没有深入细节。今天我将改变它。 什么是 Cloudflare Workers? CFW 是一个类似于 AWS Lambda 的 FaaS 平台,但它们与 Lambda 有许多
2018 年,Cloudflare 发布了 Cloudflare Workers (CFW),这是一个基于 V8 和Service Workers API 标准的 FaaS 平台。那一年,我写了一篇关于这个话题的小文章,但是并没有深入细节。今天我将改变它。
什么是 Cloudflare Workers?
CFW 是一个类似于 AWS Lambda 的 FaaS 平台,但它们与 Lambda 有许多不同之处。它们就像浏览器中的 Service Worker,但又与它们不同。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--1diJxSqT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads .s3.amazonaws.com/i/cibgm5mmzwvhnw13p1kj.png)
CFW 与 AWS Lambda 有何不同?
Lambda 基于 AWS Firecracker 构建,这是一种非常快速且小型的云虚拟化。它可以托管不同的运行时,您甚至可以通过作为 Lambda 层使用自己的运行时以您喜欢的方式执行函数。
CFW 建立在 Google V8 之上,这是为 Chrome 浏览器提供支持的 JavaScript 引擎。 V8 允许在一个进程中创建多个沙箱,这大大降低了冷启动延迟的开销。
这将我们引向 CFW 的第一个约束;您不能像使用 Lambda 层那样带来自己的运行时。但是 V8 支持 WebAssembly,所以如果一种语言支持 WebAssembly 作为编译目标,这是一种绕过这个限制的方法。
CFW 也比常规 Lambda 更接近 Lambda@Edge,因为 CFW 始终部署在 Cloudflare 网络的边缘,并且 CFW 不需要像 Lambda 那样的额外 API 网关。
对于内部用例,您可以直接调用 Lambda,但对于公共 API,您需要在它们前面有一个 API 网关。这增加了延迟、成本和复杂性。相比之下,CFW 将直接部署到 URL。
CFW 也有一些限制。他们只能使用 10ms 的 CPU 时间(付费计划中的 50ms)和 128MB 的内存。 CFW 脚本的最大容量为 1MB,每个帐户仅允许 30 个,这意味着如果您的用例无法适应 30x1MB,则不能选择 CFW。
值得注意的是,如果您的 CFW 等待某事并且不使用 CPU 时间,它可以无限期地运行,甚至在响应请求后执行操作。
CFW 的免费计划每天执行 10 万次,无限计划允许以 0.50 美元的价格执行一百万次。考虑到 CFW 不需要额外的 API 网关,这非常便宜。
CFW 与 Service Worker 有何不同?
虽然 CFW 实现了 Service Worker API,但它们有一些细微差别,最明显的区别是它们不是在浏览器中运行,而是在 Cloudflare 服务器上运行。服务器端执行为我们带来了优于 Service Worker 的第一个优势:您可以执行跨站点脚本。
CORS 对 CFW 来说不是问题。事实上,您可以使用它们通过 CFW 代理未启用 CORS 的 API,并使其直接通过浏览器访问。
它们不是 100% 符合 Service Worker API 的。出于安全原因,您不能运行eval()
、new Function
。另外,Date.now()
在执行期间不会更改,这意味着在运行时加载附加代码不起作用。
与 Service Worker 一样,它们可以用作 API 端点和浏览器之间的代理。 Cloudflare 将尝试为定义的路径执行您的工作程序,如果失败,您可以选择将请求传播到源。
Service Worker API 合规性使它们更易于前端开发人员使用,但也与 Node.js 不同,这可能导致某些库无法在 CFW 环境中运行。
部署
有两种使用 CFW 的方法。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--o0bT-bE1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/i/qspx9usskmw1ubwap4cs.png)
第一个也是最简单的一个是作为独立端点。就像您对任何 Web 服务器所做的那样。
你定义你的工人,给它一条路径,就是这样。它计算事物、渲染网站、调用一些第三方 API,无论你喜欢什么。在这种情况下,worker 有自己的 URL,并且在出错时无法传递到另一个 Web 服务器。
第二个是作为代理。它就像一个服务工作者,只是它不在浏览器的后台进程中运行。
您可以为 Web 服务器上已存在的工作程序设置路径,Cloudflare 将执行工作程序而不是您的实际端点。然后,您可以从 CFW 中调用您的端点,并在将响应发送到客户端之前对其进行处理。如果由于某种原因达到了执行限制或 CFW 错误,您可以将请求传递到您的端点,就好像什么都没发生一样。
第二个用例要求 Cloudflare 为源服务器处理 DNS。
示例:创建 CORS Proxy Worker
现在我们知道了 CFW 是什么,让我们创建一个来感受一下它们的工作原理!
先决条件
对于本教程,您需要 Node.js v12 和Cloudflare 帐户。
安装 CLI
CFW 的开发和部署是在名为 Wrangler 的 CLI 的帮助下完成的。我们将通过 NPM 安装它。
$ npm i @cloudflare/wrangler -g
进入全屏模式 退出全屏模式
初始化项目
然后可以使用 CLI 创建一个新的 CFW 项目。
$ wrangler generate cors-proxy
$ cd cors-proxy
$ npm i
进入全屏模式 退出全屏模式
实现工作脚本
我们将使用randomfox API,因为它是免费的,不需要帐户并且不支持 CORS。
新项目附带一个index.js
文件作为入口点。将文件内容替换为以下代码:
const API_URL = "https://randomfox.ca/floof/";
const PROXY_ENDPOINT = "/cors-proxy";
const HTML = `
<!DOCTYPE html>
<h1>GET without CORS Proxy:</h1>
<code id='noproxy'>Waiting</code>
<h1>GET with CORS Proxy:</h1>
<img id="proxy" src="">
<script>
(async () => {
try {
await fetch('${API_URL}');
} catch(e) {
document.getElementById("noproxy").innerHTML = e;
}
const response = await fetch(window.location.origin + '${PROXY_ENDPOINT}')
let { image } = await response.json();
document.getElementById("proxy").src = image;
})()
</script>
`;
addEventListener("fetch", (event) => {
const url = new URL(event.request.url);
if (!url.pathname.startsWith(PROXY_ENDPOINT))
return event.respondWith(
new Response(HTML, {
headers: { "content-type": "text/html;charset=UTF-8" },
})
);
if (event.request.method === "GET")
return event.respondWith(handleRequest(event.request));
return event.respondWith(
new Response(null, { status: 405, statusText: "Method not allowed" })
);
});
async function handleRequest(request) {
const url = new URL(request.url);
request = new Request(API_URL, request);
request.headers.set("Origin", new URL(API_URL).origin);
let response = await fetch(request);
response = new Response(response.body, response);
response.headers.set("Access-Control-Allow-Origin", url.origin);
response.headers.append("Vary", "Origin");
return response;
}
进入全屏模式 退出全屏模式
让我们一步一步地看一下代码。
首先,我们定义三个常量。
-
API_URL
用于 randomfox URL -
PROXY_ENDPOINT
是我们域上充当代理的路径 -
HTML
是我们将提供的示例页面,以防从浏览器访问工作人员
示例页面将获取两个 URL,一个直接来自由于缺少 CORS 标头而失败的 randomfox API,另一个来自我们的代理。然后它将图像元素的src
设置为 API 提供的 URL。
接下来,我们为 fetch 事件定义我们的事件监听器。它将以HTML
响应所有不是我们的PROXY_ENDPOINT
的路径。如果我们的PROXY_ENDPOINT
是使用 GET 方法请求的,我们将调用handleRequest
函数。
handleRequest
函数调用第三方 API 并将 CORS 标头添加到响应中,然后再将其发送回客户端。这将告诉浏览器答案对于我们的客户端 JavaScript 使用是安全的。
如果有人尝试使用不受支持的请求方法,我们将返回错误状态。
这个小例子是基于这个模板的精简版。
CORS 标头是动态的,基于请求的来源。出于安全原因,您通常使用静态域,因此只能从访问过您的域的浏览器访问工作人员。
部署工作脚本
我们再次使用 Wrangler CLI 来部署脚本。为此,我们必须将我们的帐户 ID 添加到wrangler.toml
文件中,它可以在 Cloudflare 仪表板上的菜单点 Workers 下找到。
添加 ID 后,我们可以使用以下命令进行非生产部署:
$ wrangler publish
进入全屏模式 退出全屏模式
[
](#using-the-worker)
使用工人
如果一切顺利,我们可以在https://cors-proxy.<ACCOUNT_NAME>.workers.dev
访问我们的工作人员。
总结
对于希望为其应用程序添加后端功能的前端开发人员来说,Cloudflare Workers 是一款出色的工具。无论是 API 响应的转换,还是对客户端隐藏 API 机密。如果您构建 PWA 或 JAMStack 应用程序,您可以通过 CFW 交付整个前端,而无需实际的后端。
他们对 Web 标准的遵守让您有宾至如归的感觉,只需几个命令,您就可以立即启动并运行。
您必须记住,它们不如 AWS Lambda 灵活,后者是一个更全面的平台,允许进行更多配置,并且对您可以部署的脚本数量及其文件大小有更高的限制。
更多推荐
所有评论(0)