本页比较将 sandbox 从 Sandbox SDK 0.12 迁移到 1.0 的两种方式,然后通过一次部署迁移所有 sandbox。你无法撤销将 sandbox 切换到 1.0 的那次部署。
- 你的应用运行的是
@cloudflare/sandbox0.12.14。 - 你的 1.0 类已经写好。有关该类,请参阅 替换 Sandbox 类。
- 你有一份带有独立 Wrangler 配置文件的预发布 Worker。在该文件中为 Worker 设置不同的
name,并为每个容器设置不同的name,因为wrangler deploy的--name选项不会重命名容器应用。
你可以通过以下两种方式之一迁移:
| 路径 | 会发生什么 | 适合 |
|---|---|---|
| 就地迁移 | 一次部署将所有 sandbox 迁移到 1.0。在 0.12 容器中运行的命令会结束,这些容器中的文件不会带过来。 | 生命周期短或重新创建成本低的 sandbox |
| 并排迁移 | 1.0 类与 0.12 类在同一 Worker 中并排运行。你的代码迁移每个 sandbox,当没有剩余 0.12 sandbox 时再删除 0.12 类。 | 用户会返回的长期 sandbox |
两种路径都不能用渐进式部署拆分流量。Wrangler 会拒绝混合这两个版本的部署,并出现此错误:
All Worker Versions in a multi-version deployment must declare identical Durable Object-managed Container applications.先在预发布 Worker 上排练你的路径(其中已有正在运行的 sandbox),然后再在生产环境中执行。本页其余部分按就地迁移进行。另一条路径请参阅 并排迁移 sandbox。
当将类迁移到 scheduling_policy: "durable_object" 的部署上线时,切换就会发生。0.12 sandbox 的各部分会如下变化:
| 部分 | 切换时 |
|---|---|
| 正在运行的容器 | 继续在旧容器应用中运行。部署后的短时间内,你的 Durable Object 仍会报告 running 为 true,exec() 和 getTcpPort() 仍会到达 0.12 容器。之后 running 为 false,你的代码会启动 1.0 容器。 |
| 文件 | 留在旧容器中。新容器启动时没有它们。 |
| 正在运行的命令 | 很快结束。在完成时返回结果的命令会失败并出现 HTTP 500。流式输出会以 HTTP 200 停止且没有错误。 |
| WebSockets | 停止投递数据。客户端收不到 close frame。 |
| 待处理的 alarm | 为每个曾处于活动状态的 sandbox 调用一次你的 1.0 alarm() handler。 |
schedule() 回调 |
永远不会运行。 |
| 0.12 存储键 | 保留 Durable Object 存储。迁移预览 URL、隧道和出站规则的页面会读取 portTokens、tunnels、tunnels:meta 和 OUTBOUND_CONFIGURATION。 |
-
让你的
alarm()handler 在行动前检查自己的状态。0.12 在容器运行时会保持 alarm 已设置,切换后该 alarm 会调用你的 handler。如果 handler 抛出错误,平台会以退避方式重试。在此示例中,除非nextCheckpoint时间已过,否则 handler 会返回:src/index.tsts export class MySandbox extends DurableObject<Env> { // ... async alarm(): Promise<void> { // A 0.12 alarm can call this handler once after the switch. const due = await this.ctx.storage.get<number>("nextCheckpoint"); if (due === undefined || due > Date.now()) { return; } await this.checkpoint(); } }如果你的类没有
alarm()handler,每个待处理 alarm 都会在日志中以内部错误失败一次,然后被清除。 -
替换
schedule()调用。0.12 将已调度的回调存储在 1.0 不会读取的表中。从你的类使用this.ctx.storage.setAlarm()设置下一次运行,并在alarm()中完成工作。一个 Durable Object 只有一个 alarm,因此这就是第 1 步中的 handler。要替换多个调度,请存储每次运行的时间,将 alarm 设置为最早的那次,并在alarm()中运行所有到期任务。更多信息请参阅 Alarms。 -
让客户端为静默套接字做好准备。打开的终端和预览 WebSocket 在切换时会停止接收数据,浏览器看不到它们关闭。让客户端在套接字一段时间没有收到数据时重连,或告诉用户在部署后重新加载。
-
保存用户需要的文件。0.12 容器停止后,其文件就会消失;部署后短暂期间内 1.0 代码仍可访问旧容器,这并不能作为复制文件的方式。部署前,请使用 0.12
createBackup()保存文件。切换后,请按照迁移备份中的说明恢复文件。 -
先在预发布 Worker 上排练。在那里有正在运行的 sandbox 且客户端已连接的情况下,按第 6 步和第 7 步所述将 1.0 版本上传并部署到预发布 Worker。检查切换后应用发出的请求是否正常工作。
-
上传 1.0 版本:
npx wrangler versions uploadyarn wrangler versions uploadpnpm wrangler versions upload上传会构建 1.0 镜像并创建新的容器应用。正在服务流量的版本不会改变。记下 Wrangler 打印的版本 ID。
-
在没有长时间运行的命令时部署该版本。
将
<VERSION_ID>替换为上传得到的 ID:npx wrangler versions deploy <VERSION_ID>@100% -yyarn wrangler versions deploy <VERSION_ID>@100% -ypnpm wrangler versions deploy <VERSION_ID>@100% -y
从应用程序向 sandbox 发送请求,例如运行命令或读取文件。每个 Durable Object 会在首次请求时启动 1.0 容器(此时 running 为 false)。部署后短时间内,请求仍可能到达 0.12 容器,并在 0.12 镜像中运行命令。请在部署后等待几分钟再检查。列出账户中的容器应用:
npx wrangler containers listyarn wrangler containers listpnpm wrangler containers list列表会显示你设置了 name 的新应用。旧应用仍在。Wrangler 根据你的 Worker 和类名命名它,例如 my-worker-sandbox。
删除旧容器应用。将 <OLD_APPLICATION_ID> 替换为列表中的 ID:
npx wrangler containers delete <OLD_APPLICATION_ID>yarn wrangler containers delete <OLD_APPLICATION_ID>pnpm wrangler containers delete <OLD_APPLICATION_ID>旧应用会继续运行其容器并为它们计费,直到你删除它。删除它会停止 0.12 启动的容器并删除它们的文件。Durable Objects 及其存储会保留。
0.12 写入的键会继续保留在每个 Durable Object 的存储中。只要你的类仍会读取这些键(例如迁移预览 URL、隧道和出站规则的页面),就请保留 portTokens、tunnels、tunnels:meta 和 OUTBOUND_CONFIGURATION。如果删除其他键,请在 delete() 调用中逐一指定键。不要调用 deleteAll(),它还会删除你自己的键和仍需转换的 0.12 备份句柄。