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

资源与隔离

最后更新 查看 MarkdownAgent 设置

绑定参考

两个 Preview 绑定到相同的账户级资源 ID 或名称时,会共享其数据或实例。将 Preview 绑定到不同资源即可隔离它。

资源绑定

下表显示哪些资源会自动预配,哪些需要单独的资源绑定:

资源或 previews 字段 行为 隔离单个 Preview
Durable Objects 为每个 Preview 自动预配新的 Durable Object namespace 和存储。 自动。
Containers 为每个 Preview 自动预配新的 container 应用和 container 实例。 自动。
kv_namespaces 按 id 绑定到 KV namespace。两个 Preview 共享同一 id 时共享 namespace 数据。 绑定到不同的 KV namespace。
d1_databases 按 database_id 绑定到 D1 数据库。两个 Preview 共享同一 database_id 时共享行。 绑定到不同的 D1 数据库。
r2_buckets 按 bucket_name 绑定到 R2 bucket。两个 Preview 共享同一 bucket_name 时共享对象。 绑定到不同的 R2 bucket。
queues.producers 按名称将 Queue 生产者绑定到队列。两个 Preview 共享同一队列名称时会发送到同一队列。 绑定到不同的队列。
vectorize 按 index_name 绑定到 Vectorize 索引。必须在部署前手动创建。 绑定到不同的索引。
hyperdrive 按 id 绑定到 Hyperdrive 配置。必须手动创建。真正的数据隔离需要指向不同数据库或 schema 的独立配置。 绑定到不同的 Hyperdrive 配置。
analytics_engine_datasets 写入你指定的 dataset 名称。数据集由写入隐式创建。两个 Preview 写入同一数据集时共享行。 绑定到不同的数据集名称。
pipelines 按 pipeline ID 绑定到 Pipeline stream。两个 Preview 共享同一 stream 时会将事件发送到同一目标。 绑定到不同的 stream。
workflows 绑定到现有 Workflow。调用使用该 Workflow 已部署的代码、绑定和实例。 绑定到专用的非生产 Workflow。
secrets_store_secrets 按 store_id 和 secret_name 绑定到 Secrets Store 密钥。 绑定到不同的 store 或密钥名称。
dispatch_namespaces 按 namespace 绑定到 Workers for Platforms dispatch namespace。 绑定到不同的 namespace。
mtls_certificates 按 certificate_id 绑定到 mTLS 客户端证书。 绑定到不同的证书。
vpc_services 按 service_id 绑定到 VPC service。 绑定到不同的服务。
ratelimits 创建 Rate Limiting 绑定。运行时绑定名称来自 name,而不是 binding。 使用不同的 namespace_id。
send_email 创建 Send Email 绑定。运行时绑定名称来自 name,而不是 binding。成功投递需要有效的 Email Routing 设置。 不适用。

Durable Objects

Durable Objects 使用有状态的单例模型:在同一个 namespace 内,每个对象 ID 解析为单个实例及其存储。如果 Preview 共享 namespace,它们可能读取并覆盖相同状态。对于在同一 Worker 中定义且没有 script_name 的类,每个 Preview 会自动获得自己的 namespace 和存储。

状态会在同一 Preview 的部署之间持久化,并在 Preview 删除时删除。

访问模式 Preview 配置 结果
ctx.exports 仅类和迁移 推荐。每个 Preview 会自动获得独立 namespace。
env 绑定 类、迁移和 Preview 绑定 当你的代码需要 env.COUNTER 时使用。

使用 ctx.exports(推荐)

每个 Durable Object 设置都需要从 Worker 导出 Durable Object 类,并在 Wrangler 配置中包含迁移。

使用 ctx.exports(推荐,需要 enable_ctx_exports 兼容性标志,在 compatibility_date 为 2025-11-17 或更晚时默认启用)时,仅迁移即可实现自动 Preview 隔离:

{
	// Set this to today's date
	"compatibility_date": "2026-11-14",
	"migrations": [
		{ "tag": "v1", "new_classes": ["Counter"] }
	],
	"previews": {}
}
# Set this to today's date
compatibility_date = "2026-11-14"
previews = { }

[[migrations]]
tag = "v1"
new_classes = [ "Counter" ]

生产、feature-login 和 redesign 各自获得自己的 Durable Object namespace 和存储。空的 previews 块已足够,因为不需要 Preview 专用的 Durable Object 绑定。

使用 env 绑定

如果你的代码使用 env.COUNTER,请在 previews 块中声明绑定,以便 Preview 拥有它:

{
	"durable_objects": {
		"bindings": [
			{ "name": "COUNTER", "class_name": "Counter" }
		]
	},
	"migrations": [
		{ "tag": "v1", "new_classes": ["Counter"] }
	],
	"previews": {
		"durable_objects": {
			"bindings": [
				{ "name": "COUNTER", "class_name": "Counter" }
			]
		}
	}
}
[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"

[[migrations]]
tag = "v1"
new_classes = [ "Counter" ]

[[previews.durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"

Containers

Containers 由 Durable Objects 支持。每个 Preview 都有自己的 Durable Object namespace、container 应用和 container 实例。运行 npx wrangler preview 时,Wrangler 会为该 Preview 构建并部署镜像。生成的应用名称包含 Worker、Preview 和类名,例如 my-worker_feature-login_MyContainer。

Preview 的 container 配置不会从顶层继承。如果生产和 Preview 都需要 container,请在两处都声明:

  • 顶层 containers 用于生产。
  • previews.containers 用于 Preview。
访问模式 Preview 配置 结果
ctx.exports 类、SQLite 迁移和 previews.containers 当你的代码不需要 env 绑定时推荐。
env 绑定 类、SQLite 迁移、previews.containers 和 Preview Durable Object 绑定 当你的代码调用 env.MY_CONTAINER 时使用。

在 Containers 中使用 ctx.exports

当你的 Worker 通过 ctx.exports 而不是 env 绑定访问 container 类时,使用此模式:

const container = ctx.exports.MyContainer.getByName("tenant-a");
return container.fetch(request);

声明基于 SQLite 的 Durable Object 迁移和 container 配置。将 container 配置放在 previews.containers 下,以便 Wrangler 为每个 Preview 创建 container 应用:

{
	// Set this to today's date
	"compatibility_date": "2026-11-14",
	"migrations": [
		{ "tag": "v1", "new_sqlite_classes": ["MyContainer"] }
	],
	"containers": [
		{
			"class_name": "MyContainer",
			"image": "./Dockerfile",
			"max_instances": 10,
			"instance_type": "basic"
		}
	],
	"previews": {
		"containers": [
			{
				"class_name": "MyContainer",
				"image": "./Dockerfile",
				"max_instances": 10,
				"instance_type": "basic"
			}
		]
	}
}
# Set this to today's date
compatibility_date = "2026-11-14"

[[migrations]]
tag = "v1"
new_sqlite_classes = [ "MyContainer" ]

[[containers]]
class_name = "MyContainer"
image = "./Dockerfile"
max_instances = 10
instance_type = "basic"

[[previews.containers]]
class_name = "MyContainer"
image = "./Dockerfile"
max_instances = 10
instance_type = "basic"

采用此设置时,生产和每个 Preview 使用独立的 Durable Object namespace 和独立的 container 应用。除非 Worker 代码从 env 读取 container namespace,否则不需要 previews.durable_objects 绑定。

使用 env container 绑定

如果你的代码使用 env 绑定,请在顶层为生产声明 Durable Object 绑定,并在 previews.durable_objects.bindings 下再次为 Preview 声明:

import { getContainer } from "@cloudflare/containers";

const container = getContainer(env.MY_CONTAINER, "tenant-a");
return container.fetch(request);
{
	// Set this to today's date
	"compatibility_date": "2026-11-14",
	"migrations": [
		{ "tag": "v1", "new_sqlite_classes": ["MyContainer"] }
	],
	"containers": [
		{
			"class_name": "MyContainer",
			"image": "./Dockerfile",
			"max_instances": 10,
			"instance_type": "basic"
		}
	],
	"durable_objects": {
		"bindings": [
			{ "name": "MY_CONTAINER", "class_name": "MyContainer" }
		]
	},
	"previews": {
		"containers": [
			{
				"class_name": "MyContainer",
				"image": "./Dockerfile",
				"max_instances": 10,
				"instance_type": "basic"
			}
		],
		"durable_objects": {
			"bindings": [
				{ "name": "MY_CONTAINER", "class_name": "MyContainer" }
			]
		}
	}
}
# Set this to today's date
compatibility_date = "2026-11-14"

[[migrations]]
tag = "v1"
new_sqlite_classes = [ "MyContainer" ]

[[containers]]
class_name = "MyContainer"
image = "./Dockerfile"
max_instances = 10
instance_type = "basic"

[[durable_objects.bindings]]
name = "MY_CONTAINER"
class_name = "MyContainer"

[[previews.containers]]
class_name = "MyContainer"
image = "./Dockerfile"
max_instances = 10
instance_type = "basic"

[[previews.durable_objects.bindings]]
name = "MY_CONTAINER"
class_name = "MyContainer"

使用 npx wrangler containers list 和 npx wrangler containers info <APPLICATION_ID> 检查生成的应用。Preview 中的 Container 支持是部分支持,因此在依赖它进行测试之前,请验证进程能启动并响应。

Container 应用清理

删除 Preview 会移除其 Preview 记录和 Durable Object namespace。删除传播后 Preview URL 停止提供服务,但生成的 container 应用仍可能出现在 npx wrangler containers list 中。

为确定性地清理,删除 Preview 后检查是否有残留的 container 应用:

npx wrangler preview delete --name "feature-login" --skip-confirmation
npx wrangler containers list

删除属于已删除 Preview 的任何残留应用:

npx wrangler containers delete <APPLICATION_ID>

你可以在 CI 中通过匹配生成的应用名前缀来自动清理。广泛使用此模式前请先审查 ID:

WORKER_NAME="my-worker"
PREVIEW_NAME="feature-login"
PREFIX="${WORKER_NAME}_${PREVIEW_NAME}_"

npx wrangler preview delete --name "$PREVIEW_NAME" --skip-confirmation

npx wrangler containers list --json \
	| jq -r --arg prefix "$PREFIX" '.[] | select(.name | startswith($prefix)) | .id' \
	| while read -r app_id; do
		npx wrangler containers delete "$app_id"
	done

不要仅按 Worker 名称删除 container 应用。同一 Worker 的生产应用可能有类似名称,但不包含 Preview 名称段。

D1 迁移

使用基础分支配置一个所有 Preview 默认共享的暂存数据库。需要隔离数据库的分支在自己的配置中覆盖该绑定。按以下步骤使每个分支的 D1 迁移 目标与其 Preview 绑定保持一致。

1. 配置共享暂存数据库

在基础分支上,将 Preview 绑定到 previews.d1_databases 下的共享暂存数据库。新分支会继承此配置并使用同一数据库:

wrangler.jsoncjsonc
{
	"previews": {
		"d1_databases": [
			{
				"binding": "DB",
				"database_name": "preview-shared-db",
				"database_id": "<PREVIEW_DATABASE_ID>",
			},
		],
	},
}

2. 为迁移创建 Wrangler 配置文件

在基础分支上,创建名为 wrangler.preview-migrations.jsonc 的单独文件。在顶层 d1_databases 下声明共享暂存数据库。从 previews.d1_databases 复制 database_name 和 database_id:

wrangler.preview-migrations.jsoncjsonc
{
	"d1_databases": [
		{
			"binding": "PREVIEW_DB",
			"database_name": "preview-shared-db",
			"database_id": "<PREVIEW_DATABASE_ID>",
			"migrations_dir": "migrations",
		},
	],
}

3. 为一个分支覆盖数据库(可选)

在需要隔离数据库的分支上,同时更改两个文件中的 database_name 和 database_id:

文件 要更新的绑定
wrangler.jsonc previews.d1_databases
wrangler.preview-migrations.jsonc 顶层 d1_databases

这两个文件必须指向同一物理数据库。其他分支继续使用基础分支中的共享暂存数据库。

4. 添加迁移文件

将迁移文件添加到 migrations/ 目录。要使用其他位置,请更改 wrangler.preview-migrations.jsonc 中的 migrations_dir。

5. 将迁移应用到 Preview 数据库

确认 database_name 和 database_id 与当前分支的 Preview 绑定匹配,然后应用迁移:

npx wrangler d1 migrations apply PREVIEW_DB --remote --config wrangler.preview-migrations.jsonc

如果多个 Preview 共享同一 database_id,只需为该数据库运行一次迁移命令。

6. 部署 Preview

迁移成功后,从包含其 previews.d1_databases 绑定的分支部署 Preview:

npx wrangler preview --name feature-login

限制

这些领域的 Preview 支持可能会稍后推出。如果其中某项限制阻塞了你的工作流,请在 workers-sdk 仓库中提交 issue ↗。说明该资源应共享、按 Preview 自动创建,还是在 Preview 删除时清理。

Service bindings

从 Worker A 到 Worker B 的 service binding 告诉 Cloudflare:当 Worker A 调用 env.AUTH.fetch() 时,将该请求路由到 Worker B。

目前,如果 Worker A 有到 Worker B 的 service binding,并且你部署了 Worker A 的 Preview,该 Preview 只能绑定到生产 Worker B。它不会自动绑定到 Worker B 的匹配 Preview。

如果需要让同一 Worker 内的调用留在 Preview 内部,请使用 ctx.exports 而不是 service binding。

Workflows

向 previews 块添加 Workflow 绑定会将 Preview 绑定到现有 Workflow。它不会创建或部署 Preview 专用 Workflow。要创建 Workflow,请使用 Wrangler 部署一个。

绑定到现有 Workflow 会运行该 Workflow 已部署的代码和绑定。其实例属于现有 Workflow。将绑定更改为新名称不会创建 Workflow。对该绑定的调用会失败,并出现 workflow.not_found。

对于隔离测试,请先部署专用的非生产 Workflow,然后将 Preview 绑定到它。绑定到同一 Workflow 的 Preview 会共享其实例。由另一个 Worker 拥有的 Workflow 会运行该 Worker 已部署的实现。

Cloudflare 正在开发按 Preview 自动预配 Workflow 的能力,类似于 Durable Objects。

Queue 消费者

Preview 可以向 Queues 生产消息。例如,如果其 previews 块包含 Queue 生产者绑定,Preview 可以调用 env.MY_QUEUE.send(message)。

目前 Preview 无法从 Queues 消费消息。一个 Queue 只能有一个消费者 Worker,而 Queues 服务尚未将 Preview 注册为该消费者。

请注意,Preview 生产到生产 Queue 的消息可能被生产消费。仅在此行为符合预期时,才将 Preview 指向生产 Queue。不要将每个 Preview 都指向一个共享暂存 Queue,并期望每个 Preview 的 queue(batch, env, ctx) 处理程序都会运行。只有一个消费者能收到这些消息。

Cron Triggers

Cron Trigger 告诉 Cloudflare:按此计划运行 Worker 的 scheduled() 处理程序。

Cron Triggers 面向生产。Preview 不会创建单独的计划调用,调度器目前也不会调用 Preview 的 scheduled() 处理程序。

要在 Preview 中测试计划逻辑,请将工作放在既可从 scheduled() 调用、也可从仅用于测试的路由调用的函数后面。然后在 Preview URL 上调用该测试路由。

路由

生产路由 面向生产。Preview 不会接管 zone 路由、生产自定义域、Queue 消费者或其他生产触发器。

要将 HTTP 流量发送到 Preview,请使用其 workers.dev 上的 Preview URL 或自定义域 Preview URL。自定义域 Preview URL 是独立的 Preview 主机名,例如 <preview-name>.app.example.com。

这篇文档对您有帮助吗?