创建动态调度 Worker,将传入请求路由到你的调度命名空间中的用户 Worker。 动态调度 Worker 是一种专门的路由 Worker,将传入请求定向到调度命名空间中的相应用户 Worker。与使用 Workers Routes 不同,调度 Worker 允许你通过代码以编程方式控制请求路由。
- 规模:将请求路由到数百万个主机名对应的不同 Worker,而无需为每个主机名定义 Workers Routes 配置
- 自定义路由逻辑:编写代码以精确确定请求应如何路由。例如:
- 将主机名到 Worker 的映射存储在 Workers KV 中并动态查找
- 根据子域名、路径、标头或其他请求属性路由请求
- 使用附加到自定义主机名的自定义元数据进行路由决策
- 添加平台功能:在路由层构建其他功能:
- 在请求到达用户 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。以下是你可以在调度器中实现的常见路由模式。
将路由映射存储在 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 的事件。