跳转到内容
搜索文档

放置

最后更新 查看 MarkdownAgent 设置

默认情况下,Workers 和 Pages Functions 会在距离接收请求位置最近的数据中心运行。如果您的 Worker 需要请求后端基础设施(如数据库或 API),将该 Worker 部署在更靠近后端而非最终用户的位置,可能会获得更好的性能。

{
	"placement": {
		// Use one of the following options (mutually exclusive):
		"mode": "smart", // Cloudflare automatically places your Worker closest to the upstream with the most requests
		"region": "gcp:us-east4", // Explicit cloud region to run your Worker closest to - e.g. "gcp:us-east4" or "aws:us-east-1"
		"host": "db.example.com:5432", // A host to probe (TCP/layer 4) - e.g. a database host - and place your Worker closest to
		"hostname": "api.example.com", // A hostname to probe (HTTP/layer 7) - e.g. an API endpoint - and place your Worker closest to
	},
}
[placement]
mode = "smart"
region = "gcp:us-east4"
host = "db.example.com:5432"
hostname = "api.example.com"

放置功能可以通过减少 Worker 与后端服务之间请求的往返延迟,降低 Worker 请求的整体延迟。对于运行在传统云基础设施中的数据库、API 和其他服务,您可以将延迟降至个位数毫秒级别。

选项 适用场景 配置
Smart(智能) 多个后端服务,或基础设施位置未知 mode = "smart"
Region 单个后端服务位于已知的云区域 region
Host 单个后端服务不在主流云提供商中 host 或 hostname

了解放置

假设一位位于澳大利亚悉尼的用户访问运行在 Workers 上的应用程序。该应用程序需要多次往返访问位于德国法兰克福的数据库。

一位位于澳大利亚悉尼的用户连接到同一区域的 Worker,该 Worker 随后多次往返访问位于德国法兰克福的数据库。

悉尼与法兰克福之间多次往返的延迟会不断累加。通过将 Worker 部署在数据库附近,Cloudflare 可以缩短请求的总耗时。

一位位于澳大利亚悉尼的用户连接到位于德国法兰克福的 Worker,该 Worker 随后多次往返访问同样位于德国法兰克福的数据库。

启用 Smart Placement

Smart Placement 会自动分析 Worker 的流量模式,并将其放置在最佳位置。在以下情况下使用 Smart Placement:

  • Worker 连接多个后端服务
  • 您不知道基础设施的确切位置
  • 后端服务是分布式或复制的

Smart Placement 按 Worker 分别启用。启用后,它会定期分析 Worker 在不同 Cloudflare 位置的请求持续时间。

对于每个候选位置,Smart Placement 会考虑 Worker 的性能以及转发请求所增加的网络延迟。如果某个候选位置明显更快,请求会被转发到该位置。否则,Worker 会在距离请求最近的默认位置运行。

Smart Placement 仅考虑 Worker 此前运行过的位置。它无法将 Worker 放置在通常不会收到流量的位置。

了解限制

启用 smart placement

Smart Placement 适用于所有 Workers 套餐。

使用 Wrangler 配置

在 Wrangler 配置文件中添加以下内容:

{
	"placement": {
		"mode": "smart",
	},
}
[placement]
mode = "smart"

Smart Placement 在部署后可能需要最多 15 分钟来分析 Worker。

在仪表板中配置

  1. 前往 Workers & Pages。

    Go to Workers & Pages ↗
  2. 选择您的 Worker。

  3. 前往 Settings(设置) > General。

  4. 在 Placement(放置) 下,选择 Smart(智能)。

Smart Placement 需要来自多个位置对 Worker 的稳定流量才能做出放置决策。分析过程可能需要最多 15 分钟。

检查放置状态

通过 Workers API 查询 Worker 的放置状态:

curl -X GET https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/services/$WORKER_NAME \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" | jq .

可能的放置状态:

状态 说明
(不存在) Worker 尚未被分析。它在距离请求最近的默认位置运行。
SUCCESS Worker 已被分析,将由 Smart Placement 进行优化。
INSUFFICIENT_INVOCATIONS Worker 尚未收到来自多个位置的足够请求,无法做出放置决策。
UNSUPPORTED_APPLICATION Smart Placement 使 Worker 变慢并已恢复默认放置。此状态较为罕见(少于 1% 的 Worker)。

查看请求持续时间分析

启用 Smart Placement 后,系统会收集请求持续时间数据。请求持续时间在距离最终用户最近的数据中心测量。默认情况下,1% 的请求不会通过 Smart Placement 路由,以作为对比基准。

查看 Worker 的请求持续时间分析,以衡量 Smart Placement 的影响。

检查 cf-placement 标头

启用放置后,Cloudflare 会在所有请求中添加 cf-placement 标头。使用此标头可以检查请求是否通过 Smart Placement 路由,以及 Worker 在何处处理了请求。

标头值包含放置类型和表示数据中心位置的机场代码:

  • remote-LHR — 请求通过 Smart Placement 路由到伦敦附近的数据中心。
  • local-EWR — 请求未通过 Smart Placement 路由。Worker 在纽瓦克附近的默认位置运行。

配置显式 Placement Hints

Placement Hints 允许您显式指定 Worker 的运行位置。在以下情况下使用 Placement Hints:

  • 您知道后端基础设施的确切位置
  • Worker 连接单个数据库、API 或服务
  • 基础设施是单点部署(未复制或使用 anycast)

示例包括特定区域中的主数据库、虚拟机或 Kubernetes 集群。将每次查询 20 到 30 毫秒的往返延迟降至 1 到 3 毫秒,可以改善响应时间。

指定云区域

如果您的基础设施运行在 AWS、GCP 或 Azure 上,请使用 {provider}:{region} 格式设置 placement.region 属性:

{
	"placement": {
		"region": "aws:us-east-1", // Explicit cloud region to run your Worker closest to - e.g. "gcp:us-east4" or "aws:us-east-1"
	},
}
[placement]
region = "aws:us-east-1"

Cloudflare 会将您指定的云区域映射到与该区域延迟最低的数据中心。Cloudflare 会自动调整放置以应对网络维护或变更,因此您无需指定故障转移区域。

指定主机端点

如果您的基础设施不在主流云提供商中,您可以指定一个端点供 Cloudflare 探测。Cloudflare 将三角定位外部主机的位置,并将 Workers 放置在附近的区域。

将 placement.host 设置为标识第 4 层服务。Cloudflare 使用 TCP CONNECT 检查来测量延迟,并选择最佳数据中心。

{
	"placement": {
		"host": "my_database_host.com:5432", // A host to probe (TCP/layer 4) - e.g. a database host - and place your Worker closest to
	},
}
[placement]
host = "my_database_host.com:5432"

将 placement.hostname 设置为标识第 7 层服务。Cloudflare 使用 HTTP HEAD 检查来测量延迟,并选择最佳数据中心。

{
	"placement": {
		"hostname": "my_api_server.com", // A hostname to probe (HTTP/layer 7) - e.g. an API endpoint - and place your Worker closest to
	},
}
[placement]
hostname = "my_api_server.com"

探测从公共 IP 范围发送,而非 Cloudflare IP 范围。Cloudflare 会定期重新检查服务位置。这些探测用于定位单点部署的资源,对广播、anycast、多播或复制资源无法正确工作。

列出支持的区域

Placement Hints 支持 Amazon Web Services (AWS)、Google Cloud Platform (GCP) 和 Microsoft Azure 区域标识符:

提供商 格式 示例
AWS aws:{region} aws:us-east-1、aws:us-west-2、aws:eu-central-1
GCP gcp:{region} gcp:us-east4、gcp:europe-west1、gcp:asia-east1
Azure azure:{region} azure:westeurope、azure:eastus、azure:southeastasia

有关完整区域代码列表,请参阅 AWS 区域 ↗、GCP 区域 ↗或 Azure 区域 ↗。

放置行为

无论使用 Smart Placement 还是 Placement Hints,Workers 放置的行为方式类似。以下行为对两者均适用。

了解限制

以下限制同时适用于 Smart Placement 和 Placement Hints:

cf-placement 标头

启用放置后,Cloudflare 会在所有请求中添加 cf-placement 标头。使用此标头可以检查请求是否通过放置功能路由,以及 Worker 在何处处理了请求。

标头值包含放置类型和表示数据中心位置的机场代码:

  • remote-LHR — 请求通过 Smart Placement 路由到伦敦附近的数据中心。
  • local-EWR — 请求未通过 Smart Placement 路由。Worker 在纽瓦克附近的默认位置运行。

多个 Workers

如果您在 Workers 上构建全栈应用程序,请将边缘逻辑(身份验证、路由)和后端逻辑(数据库查询、API 调用)拆分为独立的 Workers。使用 Service Bindings 通过类型安全的 RPC 连接它们。

Smart Placement 和 Service Bindings

在后端 Worker 上启用放置功能,使其在靠近数据库的位置被调用,而边缘 Worker 则在靠近用户的位置处理身份验证。

示例:边缘身份验证与已放置的后端

此示例展示两个 Workers:

  • auth-worker — 在边缘运行(无放置),处理身份验证
  • app-worker — 部署在数据库附近,处理数据查询
{
	"name": "auth-worker",
	"main": "src/index.ts",
	"services": [{ "binding": "APP", "service": "app-worker" }],
}
name = "auth-worker"
main = "src/index.ts"

[[services]]
binding = "APP"
service = "app-worker"
auth-worker/src/index.tsts
import { AppWorker } from "../app-worker/src/index";

interface Env {
	APP: Service<AppWorker>;
}

export default {
	async fetch(request: Request, env: Env): Promise<Response> {
		const authHeader = request.headers.get("Authorization");
		if (!authHeader?.startsWith("Bearer ")) {
			return new Response("Unauthorized", { status: 401 });
		}

		const userId = await validateToken(authHeader.slice(7));
		if (!userId) {
			return new Response("Invalid token", { status: 403 });
		}

		// Call the placed back-end Worker via RPC
		const data = await env.APP.getUser(userId);
		return Response.json(data);
	},
};

async function validateToken(token: string): Promise<string | null> {
	return token === "valid" ? "user-123" : null;
}
{
	"name": "app-worker",
	"main": "src/index.ts",
	"placement": {
		// Use one of the following options (mutually exclusive):
		// "mode": "smart", // Cloudflare automatically places your Worker closest to the upstream with the most requests
		"region": "aws:us-east-1", // Explicit cloud region to run your Worker closest to - e.g. "gcp:us-east4" or "aws:us-east-1"
		// "host": "db.example.com:5432", // A host to probe (TCP/layer 4) - e.g. a database host - and place your Worker closest to
		// "hostname": "api.example.com", // A hostname to probe (HTTP/layer 7) - e.g. an API endpoint - and place your Worker closest to
	},
}
name = "app-worker"
main = "src/index.ts"

[placement]
region = "aws:us-east-1"
app-worker/src/index.tsts
import { WorkerEntrypoint } from "cloudflare:workers";

export default class AppWorker extends WorkerEntrypoint {
	async fetch() {
		return new Response(null, { status: 404 });
	}

	// Each method runs near your database - multiple queries stay fast
	async getUser(userId: string) {
		const user = await this.env.DB.prepare("SELECT * FROM users WHERE id = ?")
			.bind(userId)
			.first();
		return user;
	}

	async getUserListings(userId: string) {
		// Multiple round-trips to the DB are low-latency when placed nearby
		const user = await this.env.DB.prepare("SELECT * FROM users WHERE id = ?")
			.bind(userId)
			.first();
		const listings = await this.env.DB.prepare(
			"SELECT * FROM listings WHERE owner_id = ?",
		)
			.bind(userId)
			.all();
		const reviews = await this.env.DB.prepare(
			"SELECT * FROM reviews WHERE listing_id IN (SELECT id FROM listings WHERE owner_id = ?)",
		)
			.bind(userId)
			.all();

		return { user, listings: listings.results, reviews: reviews.results };
	}
}

auth-worker 在边缘运行,可快速拒绝未授权请求。已授权的请求通过 RPC 转发到 app-worker,后者在数据库附近运行以实现快速查询。

Durable Objects

Durable Objects 无需配置即可提供自动放置。对 Durable Object 内嵌 SQLite 数据库 的查询实际上是零延迟 ↗的,因为计算与数据运行在同一进程中。

尽可能在 Durable Object 内完成工作并返回组合结果,而不是从 Worker 发起多次往返:

src/index.tsts
import { DurableObject } from "cloudflare:workers";

type Session = { id: string; user_id: string; created_at: number };
type PromptHistory = {
	id: string;
	session_id: string;
	role: string;
	content: string;
};

export class AgentHistory extends DurableObject {
	async getSessionContext(sessionId: string) {
		// All queries execute with zero network latency — compute and data are colocated
		const session = this.ctx.storage.sql
			.exec<Session>("SELECT * FROM sessions WHERE id = ?", sessionId)
			.one();
		const prompts = this.ctx.storage.sql
			.exec<PromptHistory>(
				"SELECT * FROM prompt_history WHERE session_id = ? ORDER BY created_at",
				sessionId,
			)
			.toArray();

		return { session, prompts };
	}
}

这篇文档对您有帮助吗?