跳转到内容
本站为社区维护的非官方中文翻译,与 Cloudflare, Inc. 无关联。本站不提供账户登录,请勿在任何非官方站点输入您的 Cloudflare 账户信息。官方文档:developers.cloudflare.com

Container 生命周期

最后更新 查看 MarkdownAgent 设置

部署

镜像和正在运行的 Container 实例如何更新,取决于应用的调度策略。

使用 durable_object 策略时,Wrangler 会为应用准备具名镜像。Durable Object 代码可以访问其不可变引用,并在调用 ctx.container.start() 时选择镜像和实例规格。当镜像引用变化时,Durable Object 代码决定是停止正在运行的 Container 并用新镜像启动,还是让它继续使用先前镜像。这种由应用控制的重启,就是在 durable_object 策略下推出镜像变更的方式。这些实例不参与应用范围的镜像滚动发布。

使用 default 策略时,Wrangler 上传或解析应用镜像。Cloudflare 将该镜像分发到其网络,并为新实例准备容量。对镜像或实例类型的变更会使用滚动发布。

Worker 代码会在部署时立即生效,不必等待任何应用范围的 Container 滚动发布完成。请参阅部署 Containers。

容器实例生命周期

flowchart LR
    accTitle: Container instance lifecycle
    accDescr: A Worker accesses a container through its Durable Object. The container moves from stopped to starting, running but not ready, ready for traffic, stopping, and stopped.

    Worker["Worker"] -->|Durable Object binding| DurableObject["Durable Object"]
    DurableObject -->|<code>ctx.container</code>| Container

    subgraph Container["Container instance"]
        direction TD
        Stopped["Stopped"]
        Starting["Starting<br/><code>start()</code> called"]
        Running["Running<br/>Not ready"]
        Ready["Ready<br/>Accepting traffic"]
        Stopping["Stopping<br/>Stop requested"]
        StoppedAgain["Stopped"]

        Stopped --> Starting --> Running --> Ready --> Stopping --> StoppedAgain
    end

只能通过其 Durable Object 访问 Container。Worker 将请求发送到 Durable Object,后者通过 ctx.container 访问 Container。

空闲超时、signal()、destroy()、滚动发布或进程退出都可以停止实例。如果启动失败或进程提前退出,实例会回到已停止状态。

ctx.container.running 属性会在进程准备好接受流量之前变为 true。发送第一个请求前,请检查端口就绪。

对于新应用,请通过 Durable Object Container API 管理此生命周期。它让 Durable Object 可以将容器计算与持久状态和警报(alarms)协调起来。现有应用可以使用 Container 类。要比较这两种 API,请参阅 Containers API。

请求生命周期

从客户端到 Worker

回想一下,Containers 由 Durable Objects 和 Workers 支持。 请求首先通过 Worker 路由,通常由在请求用户之间拥有最佳延迟的位置的数据中心处理。 如果开启了智能放置(Smart Placement),或者最近的位置处于高负载状态,则可能会选择不同的数据中心来优化整体延迟。

由于所有 Container 请求都通过 Worker 传递,终端用户无法向容器实例发出非 HTTP 的 TCP 或 UDP 请求。如果你有需要终端用户入站 TCP 或 UDP 的用例,请让我们知道 ↗。

从 Worker 到 Durable Object

从 Worker,请求通过一个 Durable Object 实例传递。你可以扩展 DurableObject 并直接使用 ctx.container,或扩展 Container 类。 每个 Durable Object 实例都是一个全局可路由的隔离区,可以执行代码并存储状态。这允许开发人员寻址并路由到特定容器实例、在容器退出时运行代码,以及存储与每个实例关联的持久状态。

启动容器

当 Durable Object 请求新的容器实例时,Cloudflare 会选择具备所需镜像的合格容量。durable_object 策略使用提供给 ctx.container.start() 的 image 和 instance 选项。default 策略使用 Wrangler 配置中的应用镜像和实例类型。

启动其他容器实例可以使用镜像可用的其他位置。随着需求增长,Cloudflare 会准备额外容量。因为已准备的容量是有限的,某些容器实例可能会在距离终端用户更远的位置启动。你只需为正在运行的实例付费,而不需要为未运行的预热镜像付费。

冷启动

冷启动是指容器实例从完全停止的状态启动。 如果你使用一个全新的 ID 调用 env.MY_CONTAINER.get(id) 并且首次启动此实例,则会导致冷启动。 这将首次从其入口点启动容器镜像。根据此入口点执行的操作,启动需要不同长度的时间。

容器冷启动通常在 1-3 秒范围内,但这取决于镜像大小和代码执行时间等因素。

向正在运行的容器发起请求

当请求启动新的容器实例时,会选择具有预先拉取镜像的最近位置。 之后无论它们源自何处,对该特定实例的后续请求,只要该实例保持活动状态,就会被路由到这个位置。

但是,一旦该容器实例停止并重新启动,将来的请求可能会被路由到一个不同的位置。 这个位置将再次是距离源请求最近的具有预先拉取镜像的位置。

容器运行时

每个容器实例都在带有自己的内核和网络的 Firecracker microVM 中运行。Cloudflare 网络上的其他工作负载不会共享该内核。你的镜像作为 Linux 容器在 VM 内运行。

容器应针对 linux/amd64 架构构建,并应保持在大小限制内。

日志记录、指标收集和网络会根据开发人员的配置自动在每个容器上设置。

容器关闭

使用 Durable Object Container API 时,调用 setInactivityTimeout(),让运行时在 Durable Object 变为空闲后停止容器。Durable Object 在停止接收请求时变为空闲。超时可以在 Durable Object 休眠时保持容器可用。你也可以使用 signal() 或 destroy() 停止容器。

Container 类将 sleepAfter 默认设置为 10 分钟。其 onActivityExpired() 实现会调用 stop()。你可以更改持续时间或覆盖该钩子。

当平台即将停止容器实例时,它会:

  1. 向容器中的主进程发送 SIGTERM。
  2. 最多等待 15 分钟让该进程退出。
  3. 如果进程仍在运行,则发送 SIGKILL。

如果你需要在退出前进行清理,请在镜像中处理 SIGTERM。滚动发布用新镜像替换容器实例时,会运行相同的序列。

生命周期事件

Durable Object Container API 提供 monitor()。其 Promise 在容器退出时解析,在容器出错时拒绝。

Container 类会添加钩子,在容器状态改变时运行 Worker 代码:

  • onStart() — 容器启动后运行。
  • onStop() — 容器进程退出后运行。接收退出码和停止原因。
  • onActivityExpired() — 在 sleepAfter 计时器到期且没有传入请求时运行。默认实现调用 stop() 关闭容器。你可以用它仅在特定条件下停止容器。
  • onError() — 在容器启动或端口检查失败时运行。

完整实现请参阅状态钩子示例。

使用快照

默认情况下,所有磁盘都是临时的。当容器实例进入休眠状态时,下次启动会使用来自容器镜像的全新磁盘。

如果你需要某个时间点的文件系统状态,使用 durable_object 调度策略 的 Container 应用可以创建和恢复快照。快照是不可变的,因此后续文件更改需要新的快照。更多信息请参阅快照。

你还可以使用 FUSE 将磁盘持久化到 R2 或其他对象存储后端。但是,你不应期望在使用 FUSE 时获得原生类 SSD 的性能。

一个示例请求

  • 开发者部署了一个 Container。Cloudflare 会在其网络中自动准备好实例。
  • 来自阿根廷巴里洛切的客户端发出请求。它到达了位于阿根廷内乌肯附近的 Cloudflare 位置的 Worker。
  • 此 Worker 请求调用 getContainer(env.MY_CONTAINER, "session-1337")。在底层,这会启动 Durable Object,然后调用 this.ctx.container.start。
  • 这将请求最近的空闲容器实例。Cloudflare 识别到阿根廷布宜诺斯艾利斯有一个空闲实例,并在那里启动它。
  • 不同的用户需要路由到同一个容器。该用户的请求到达了运行在美国圣地亚哥的 Cloudflare 位置的 Worker。
  • Worker 再次调用 getContainer(env.MY_CONTAINER, "session-1337")。
  • 如果初始容器实例仍在运行,请求将被路由到布宜诺斯艾利斯的原始位置。如果初始容器已进入休眠状态,Cloudflare 将再次尝试查找最近的容器“空闲”实例,可能在北美,并在那里启动实例。

这篇文档对您有帮助吗?