跳转到内容
搜索文档

动态调度 Worker

最后更新 查看 MarkdownAgent 设置

创建动态调度 Worker,将传入请求路由到你的调度命名空间中的用户 Worker。 动态调度 Worker 是一种专门的路由 Worker,将传入请求定向到调度命名空间中的相应用户 Worker。与使用 Workers Routes 不同,调度 Worker 允许你通过代码以编程方式控制请求路由。

图 1:Workers for Platforms:主流程

为什么使用动态调度 Worker?

  • 规模:将请求路由到数百万个主机名对应的不同 Worker,而无需为每个主机名定义 Workers Routes 配置
  • 自定义路由逻辑:编写代码以精确确定请求应如何路由。例如:
  • 添加平台功能:在路由层构建其他功能:
    • 在请求到达用户 Worker 之前运行身份验证检查
    • 从传入请求中移除或添加标头或元数据
    • 附加有用的上下文,例如用户 ID 或账户信息
    • 根据需要转换请求或响应

配置调度命名空间绑定

要允许动态调度 Worker 动态地将请求路由到命名空间中的 Worker,你需要配置调度命名空间绑定(binding)。此绑定使动态调度 Worker 能够使用 env.dispatcher.get() 调用该命名空间中的任何用户 Worker。

{
	"dispatch_namespaces": [
		{
			"binding": "DISPATCHER",
			"namespace": "my-dispatch-namespace"
		}
	]
}
[[dispatch_namespaces]]
binding = "DISPATCHER"
namespace = "my-dispatch-namespace"

绑定配置完成后,你的动态调度 Worker 可以将请求路由到命名空间中的任何 Worker。以下是你可以在调度器中实现的常见路由模式。

路由示例

图 2:Workers for Platforms:主流程

基于 KV 的路由

将路由映射存储在 Workers KV 中。这样你可以修改路由逻辑,而无需更改或重新部署动态调度 Worker。

export default {
	async fetch(request, env) {
		try {
			const url = new URL(request.url);

			// Use hostname, path, or any combination as the routing key
			const routingKey = url.hostname;

			// Lookup user Worker name from KV store
			const userWorkerName = await env.USER_ROUTING.get(routingKey);

			if (!userWorkerName) {
				return new Response("Route not configured", { status: 404 });
			}

			// Optional: Cache the KV lookup result
			const userWorker = env.DISPATCHER.get(userWorkerName);
			return await userWorker.fetch(request);
		} catch (e) {
			if (e.message.startsWith("Worker not found")) {
				return new Response("", { status: 404 });
			}
			return new Response(e.message, { status: 500 });
		}
	},
};

基于子域名的路由

将子域名路由到相应的 Worker。例如,my-customer.example.com 将路由到调度命名空间中名为 my-customer 的 Worker。

export default {
	async fetch(request, env) {
		try {
			// Extract user Worker name from subdomain
			// Example: customer1.example.com -> customer1
			const url = new URL(request.url);
			const userWorkerName = url.hostname.split(".")[0];

			// Get user Worker from dispatch namespace
			const userWorker = env.DISPATCHER.get(userWorkerName);
			return await userWorker.fetch(request);
		} catch (e) {
			if (e.message.startsWith("Worker not found")) {
				// User Worker doesn't exist in dispatch namespace
				return new Response("", { status: 404 });
			}
			// Could be any other exception from fetch() or from the dispatched Worker
			return new Response(e.message, { status: 500 });
		}
	},
};

基于路径的路由

将 URL 路径路由到相应的 Worker。例如,example.com/customer-1 将路由到调度命名空间中名为 customer-1 的 Worker。

export default {
	async fetch(request, env) {
		try {
			const url = new URL(request.url);
			const pathParts = url.pathname.split("/").filter(Boolean);

			if (pathParts.length === 0) {
				return new Response("Invalid path", { status: 400 });
			}

			// example.com/customer-1 -> routes to 'customer-1' worker
			const userWorkerName = pathParts[0];

			const userWorker = env.DISPATCHER.get(userWorkerName);
			return await userWorker.fetch(request);
		} catch (e) {
			if (e.message.startsWith("Worker not found")) {
				return new Response("", { status: 404 });
			}
			return new Response(e.message, { status: 500 });
		}
	},
};

强制执行自定义限制

使用自定义限制控制给定用户 Worker 可以使用多少 CPU 时间,或可以发出多少子请求。你可以根据客户计划类型或其他条件设置不同的限制。

export default {
	async fetch(request, env) {
		try {
			const url = new URL(request.url);
			const userWorkerName = url.hostname.split(".")[0];

			// Look up customer plan from your database or KV
			const customerPlan = await env.CUSTOMERS.get(userWorkerName);

			// Set limits based on plan type
			const plans = {
				enterprise: { cpuMs: 50, subRequests: 50 },
				pro: { cpuMs: 20, subRequests: 20 },
				free: { cpuMs: 10, subRequests: 5 },
			};
			const limits = plans[customerPlan] || plans.free;

			const userWorker = env.DISPATCHER.get(userWorkerName, {}, { limits });
			return await userWorker.fetch(request);
		} catch (e) {
			if (e.message.startsWith("Worker not found")) {
				return new Response("", { status: 404 });
			}
			if (e.message.includes("CPU time limit")) {
				// Track limit violations with Analytics Engine
				env.ANALYTICS.writeDataPoint({
					indexes: [userWorkerName],
					blobs: ["cpu_limit_exceeded"],
				});
				return new Response("CPU limit exceeded", { status: 429 });
			}
			return new Response(e.message, { status: 500 });
		}
	},
};

有关可用限制的更多详细信息,请参阅自定义限制

要跟踪用户 Worker 中的限制违规和其他指标,请使用 Workers Analytics Engine。有关详细日志记录和调试,请配置 Tail Worker 以捕获来自调度 Worker 的事件。

这篇文档对您有帮助吗?