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

Sandbox 生命周期

最后更新 查看 MarkdownAgent 设置

Linux 沙盒是一个用于启动和停止容器的 Durable Object。Worker 通过名称(例如会话 ID)访问 Durable Object;相同名称始终会访问同一个 Durable Object。收到工作请求时,Durable Object 会调用 this.ctx.container.start() 来启动容器实例:这是一台运行你所用镜像的 Linux 虚拟机,拥有独立的进程和磁盘。

Durable Object 和实例的存续时间不同。Durable Object 会保留其存储内容,例如会话详情或快照 ID,直到代码将其删除。实例只会运行到被停止为止,其进程和磁盘文件也会随之结束。下一次调用 start() 会创建新实例。

本页以编程 Agent 为例。Agent 克隆仓库、安装依赖、编辑文件并启动开发 server。然后它会等待一小时,再按名称访问同一个 sandbox。如果实例一直在运行,或应用保存了 snapshot,文件就会还在。开发 server 只有在实例一直运行时才会还在。

Instance running
The Linux instance runs a development server and holds the repository and edits on its disk.

活动会让实例保持运行

Durable Object 处于活动状态时,实例会持续运行。Durable Object 处理请求、运行闹钟、流式传输响应,或通过 accept() 接受并保持 WebSocket 打开时,都处于活动状态。浏览器终端会以这种方式保持沙盒运行,即使没有人输入内容也一样。

Durable Object 变为非活动状态后,实例会根据 setInactivityTimeout() 设置的时间继续运行,最长为 6 小时。在此期间到达的请求会连接到同一个实例,并继续使用其文件和进程。若未设置超时,Cloudflare 会在 Durable Object 变为非活动状态后不久停止实例。

在实例内部运行的代码不计为活动状态。如果没有请求到达,即使构建、测试套件或 Agent 任务仍在运行,实例也会在非活动超时结束时停止。运行频率高于该超时的 Durable Object 闹钟可以检查工作状态,并让实例保持运行,直到工作结束。如需每分钟运行一次的闹钟,请参阅运行后台进程。

空闲实例仍会产生费用

实例运行期间,Containers 会按其内存和磁盘计费,无论实例内部是否正在处理工作。实例停止后便不再计费。如需了解费率,请参阅 Containers 定价。

如果非活动超时时间长于两次请求之间的等待时间,进程会在等待期间继续运行,你需要为该实例付费,直到下一次请求到达。较短的超时会让实例停止。随后,快照会将文件带到下一个实例,由新实例重新启动进程。若要让开发服务器持续运行一小时,编码 Agent 需要设置长于一小时的超时,并为这一个小时的实例运行时间付费。

超时不会在重启后保留

Durable Object 离开内存后,稍后再次运行其构造函数时会重启,例如在部署后或两次闹钟之间。实例可能会在重启期间继续运行。重启后的 Durable Object 不会设置非活动超时,因此实例会在 Durable Object 变为非活动状态后不久停止。

sandbox 示例在 start() 之后设置超时,并在实例已在运行时于 Durable Object 的构造函数中再次设置。示例请参阅 setInactivityTimeout()。

什么会停止实例

出现以下任一情况时,实例会停止:

  • 不活动超时结束。
  • 你的 Worker 调用 destroy()。
  • 主进程退出。
  • 平台事件会停止实例,例如服务器重启。Cloudflare 不保证实例会运行固定时长。

主进程是传给 start() 的 entrypoint,或镜像的默认命令。主进程退出时,实例会停止,所有通过 exec() 启动的命令也会随之结束。cloudflare/debian-trixie 的默认命令会立即退出,因此 sandbox 示例以 sleep infinity 作为 entrypoint 启动该镜像,或将 Web server 作为主进程运行。

非活动超时结束时,实例中的每个进程都会收到 SIGTERM,Cloudflare 随后不久便会停止实例,无论进程是否已退出。destroy() 会立即停止实例,进程没有时间进行清理。不要依赖 SIGTERM 处理程序完成工作。实例停止前,请保存所需文件,例如保存到快照中。

Cloudflare 不会在实例停止时唤醒 Durable Object。只有 Durable Object 仍在内存中时,待处理的 monitor() 调用才会报告停止事件。从调用开始算起,该调用最多会让 Durable Object 在内存中保留 15 分钟。对于 2026-10-01 之前的兼容日期,Durable Object 会在通常的空闲时段后离开内存,除非 Worker 设置了 durable_object_io_tasks_prevent_eviction 标志。只有 Durable Object 离开内存后,非活动超时才开始计时;因此实例会在超时之后继续运行,Durable Object 也会继续产生持续时间费用。Durable Object 离开内存时,调用会结束,但不会报告随后发生的停止事件。

如需记录每次停止事件及其原因,请参阅在沙盒停止时运行代码。

部署会让实例继续运行

部署 Worker 的新版本会重启每个 Durable Object。正在运行的实例会继续运行,下一个请求会到达同一个实例,并带有其文件和进程。Durable Object 通过 interceptOutboundHttp() 设置的出站 handler 会保留,并运行新版本的代码。

正在运行的实例会保留启动时使用的镜像、entrypoint 和环境变量。实例运行期间调用 start() 会抛出错误,因此新镜像或新的启动选项仅会应用于部署后启动的实例。要将 sandbox 迁移到新镜像,请先停止其实例(例如使用 destroy()),然后再启动新实例。旧实例的文件和进程会随其一同结束。

部署期间,沙盒正在处理的请求、流式响应和 WebSocket 可以继续由旧版本处理。在这些工作结束之前,旧版本也可以继续处理该沙盒的新请求,因此新代码可能要等沙盒空闲后才能运行。因此,部署不能用来取消工作。运行时仍可能关闭 Durable Object,因此浏览器终端等客户端应在连接关闭时重新连接。更多信息请参阅关闭行为。

部署后,实例会按照旧版本设置的非活动超时继续运行。新版本必须重新设置超时,具体请参阅超时不会在重启后保留。

Container 滚动发布 只会替换使用默认调度策略 的 Container 应用中的实例,因此滚动发布不会替换 sandbox。

Snapshot 会将文件带到下一个实例

实例磁盘存放代码仓库、已安装的软件包、配置文件,以及命令写入的输出。实例内存存放运行中的进程、打开的终端和网络连接。实例停止时,这些内容都会消失;下一个实例会从镜像或快照启动。

snapshotContainer() 会保存正在运行实例的可写根文件系统。它不会保存单独挂载的文件系统、内存或进程。从 snapshot 启动会创建带有已保存文件的新实例,新实例会运行其 entrypoint。先前运行的进程不会继续。新实例会复用相同的进程 ID,因此文件中保存的进程 ID 在恢复后可能属于另一个进程。/run 中的文件位于内存中,snapshot 不会保存它们。

由应用决定何时保存快照。应用会存储快照(例如存储在 Durable Object 存储中),并将其传给下一次 start()。Cloudflare 不会自行恢复快照。上次快照之后所做的更改只存在于当前实例中;实例也可能在没有警告的情况下停止,因此请在完成需要保留的工作后保存快照。

snapshot 会在创建或最近一次恢复后 30 天过期。若要更长时间保留文件,请将它们复制到 bucket。

编程 Agent 的仓库、依赖和编辑内容会从 snapshot 恢复。开发 server 不会恢复,因此 Agent 需要再次启动它。要保存并恢复工作区,请参阅 使用 snapshot 保存并恢复 sandbox。要在 sandbox 因不活动而停止时自动保存,请参阅 自动保存 sandbox。

挂载的 bucket 会比每个实例都更久

挂载的 R2 bucket 中的文件是该 bucket 中的对象。每个实例停止后它们仍然存在,其他有权访问该 bucket 的 sandbox 和 Worker 也可以读取它们。snapshot 不包含挂载的目录,挂载会随其实例结束,因此每个新实例都需要再次挂载该 bucket。

对属于持续工作区的文件使用 snapshot。对其他系统需要读取、或必须比工作区更长久的文件使用 bucket。要挂载 bucket,请参阅 挂载 R2 bucket。

相关资源

这篇文档对您有帮助吗?