订阅以接收新文章的通知:

介绍 Services:在 Cloudflare Workers 上构建可组合、分布式应用

2021-11-16

3 分钟阅读时间
这篇博文也有 English日本語版本。
Introducing Services: Build Composable, Distributed Applications on Cloudflare Workers

首先是 Worker 脚本。它很简单,但很巧妙。只需几行代码,您就可以重写 HTTP 请求、附加标头或快速修复您的网站。

但是,如果您想在 Workers 上构建一个完整的应用程序该怎么办?您的开发人员工具箱中将需要更多工具。这就是我们在 Workers 平台引入扩展的原因,比如我们的分布式键值存储库 KVDurable Objects — 一个一致性程度高、面向对象的数据库;很快会引入 R2 (无出口对象存储)。虽然这些工具允许您构建更健壮的应用程序,但在构建由_许多_应用程序或服务组成的系统架构方面仍然存在差距。

假设您已经构建了一个身份验证服务用于授权对您的 API 的请求。您想在您所有的其他服务中重复使用这个逻辑。此外,当您对该身份验证服务进行修改时,您想在受控环境中测试它,而不会影响其他已投入使用的服务。暂时就假设这么多了。

介绍服务

服务是 Cloudflare Workers 上用于部署应用程序的新构建块。与脚本不同的是,服务是可组合的,这使得服务能够相互对话。服务还支持多个环境,这可让您在预览环境中测试更改,然后在您确信更改可行时再推广到生产环境。

为了实现向服务的无缝过渡,我们已经自动迁移了每一个脚本,使其成为具有一个“生产”环境的服务 — 不需要执行任何操作。

服务具有环境

每项服务都具有一个生产环境,并且能够创建或克隆几十个预览环境。一个环境的每一个方面都是可以覆盖的:代码、环境变量,甚至诸如 KV 命名空间之类的资源。您只需在仪表板上点击几下,就可以创建和切换环境。

每个环境都可以通过唯一的主机名来解析,这个主机名是在您创建或重命名环境时自动生成的。部署后无需等待。您需要的一切,如 DNS 记录、SSL 证书等,几秒钟后即可使用。如果您想要更高级的设置,您还可以添加从您的域到环境的自定义路由。

一旦您在预览环境中测试了您的更改,您就可以推广到生产环境了。我们已经使代码从一个环境推广到另一个环境变得非常容易,而不需要再次重建或上传您的代码。环境也会将代码与设置分开管理,所以当您从暂存环境推广到生产环境时,您不需要手动编辑环境变量。

对服务进行版本控制

对服务的每一次更改都进行版本控制和审计。错误确实会发生,但是当错误发生时,重要的是能够快速回滚,然后有工具可以回答这个老问题:“谁在什么时候更改了什么内容?”

Each environment has a version history.

服务中的每个环境都有自己的版本历史记录。每次更改代码或更新环境变量时,该环境的版本号都会递增。您也可以给每个版本添加额外的元数据,比如 git commit 或部署标记。

服务可以相互对话

服务是可组合的,这允许一个服务与另一个服务对话。为了支持这一点,我们将引入一个新的 API 来促进服务与服务之间的通信:服务绑定。

Service bindings open up a world of composability

服务绑定允许您向另一个服务发送 HTTP 请求,而这些请求不会通过互联网传递。这意味着您可以直接从您的代码中调用其他 Workers!服务绑定开辟了一个全新的可组合性世界。在下面的例子中,请求由一个身份验证服务来验证。

export default {
  async fetch(request, environment) {
    const response = await environment.AUTH.fetch(request);
    if (response.status !== 200) {
      return response;
    }
    return new Response("Authenticated!");
  }
}
Service Bindings allow for separation of concerns

服务绑定使用标准的 fetch API,因此您可以继续使用现有的实用程序和库。您还可以更改服务绑定的环境,以便您可以测试服务的新版本。在下一个示例中,1% 的请求被路由到服务的“canary”部署。如果对 canary 的请求失败,则会将该请求发送到生产部署以寻求另一个机会。

export default {
  canRetry(request) {
    return request.method === "GET" || request.method === "HEAD";
  },
  async fetch(request, environment) {
    if (Math.random() < 0.01) {
      const response = await environment.CANARY.fetch(request.clone());
      if (response.status < 500 || !canRetry(request)) {
        return response;
      }
    }
    return environment.PRODUCTION.fetch(request);
  }
}

虽然服务之间的接口是 HTTP,但联网不是使用 HTTP 进行。实际上根本不需要联网!与典型的“微服务架构”不同(其中服务通过网络进行通信并且可能会受到延迟或中断的影响),服务绑定是一种零成本的抽象。当您部署服务时,我们会构建其服务绑定的依赖关系图,然后将所有这些服务打包到一个部署中。当一个服务调用另一个服务时,不会出现网络延迟; 请求会立即执行。

Classic service-oriented architecture; versus service bindings

这种零成本模型使团队能够在其组织内共享和重复使用代码,而不受延迟或性能影响。抛却令人费解的 YAML 模板或编排服务吧 — 只需编写代码,我们将把它们拼接在一起。

立即行动,试试未来技术吧!

我们很高兴地宣布您今天就可以开始使用服务了! 如果您已经使用过 Workers,您会注意到您的每个脚本都已升级为具有一个“生产”环境的服务。仪表板和所有现有的 Cloudflare API 将继续与服务一起“正常工作”。

作为公开测试版发布的一部分,您还可以创建代码并将其部署到多个“预览”环境。我们仍在研究服务绑定和版本控制,我们将在您开始使用它们后立即提供更新。

有关服务的更多信息,请查看以下任何资源:

我们保护整个企业网络,帮助客户高效构建互联网规模的应用程序,加速任何网站或互联网应用程序抵御 DDoS 攻击,防止黑客入侵,并能协助您实现 Zero Trust 的过程

从任何设备访问 1.1.1.1,以开始使用我们的免费应用程序,帮助您更快、更安全地访问互联网。要进一步了解我们帮助构建更美好互联网的使命,请从这里开始。如果您正在寻找新的职业方向,请查看我们的空缺职位
Full Stack WeekCloudflare Workers开发人员Developer Platform

在 X 上关注

Ashcon Partovi|@ashconpartovi
Kabir Sikand|@kabirsikand
Cloudflare|@cloudflare

相关帖子

2024年10月09日 13:00

Improving platform resilience at Cloudflare through automation

We realized that we need a way to automatically heal our platform from an operations perspective, and designed and built a workflow orchestration platform to provide these self-healing capabilities across our global network. We explore how this has helped us to reduce the impact on our customers due to operational issues, and the rich variety of similar problems it has empowered us to solve....

2024年9月27日 13:00

Our container platform is in production. It has GPUs. Here’s an early look

We’ve been working on something new — a platform for running containers across Cloudflare’s network. We already use it in production, for AI inference and more. Today we want to share an early look at how it’s built, why we built it, and how we use it ourselves. ...