INTEGRITY Dokumentace

Dynamický dispatch Worker

A dynamic dispatch Worker je specializovaný směrovací Worker, který přesměrovává příchozí požadavky na příslušné uživatelské Workery ve vašem dispatch namespace. Místo použití Trasy Workerů, dispatch Workers vám umožňují programově řídit směrování požadavků pomocí kódu.

Obrázek 1: Workers for Platforms: hlavní tok

Proč používat dynamic dispatch Worker?

Nakonfigurujte vazbu dispatch namespace

Aby váš dynamický dispatch Worker mohl dynamicky směrovat požadavky na Workery v namespace, musíte nakonfigurovat dispatch namespace binding. Tento binding umožňuje vašemu dynamic dispatch Workeru volat libovolný user Worker v rámci daného namespace pomocí env.dispatcher.get().

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

Jakmile je binding nakonfigurovaný, může váš dynamic dispatch Worker směrovat požadavky na libovolný Worker v namespace. Níže najdete běžné vzory směrování, které můžete ve svém dispatcheru implementovat.

Příklady směrování

Obrázek 2: Workers for Platforms: hlavní tok

Směrování založené na KV

Ukládejte mapování směrování do Workers KV. Díky tomu můžete upravovat logiku směrování, aniž byste museli měnit nebo znovu nasazovat dynamic dispatch 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 });
		}
	},
};

Směrování založené na subdoméně

Směrujte subdomény na odpovídající Worker. Například my-customer.example.com bude směrováno na Worker s názvem my-customer v dispatch namespace.

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 });
		}
	},
};

Směrování na základě cesty

Směrujte cesty URL na odpovídající Worker. Například example.com/customer-1 bude směrováno na Worker s názvem customer-1 v dispatch namespace.

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 });
		}
	},
};

Vynucujte vlastní limity

Použijte vlastní limity k tomu, abyste omezili, kolik CPU času může daný uživatelský Worker využít nebo kolik subrequestů může vytvořit. Různé limity můžete nastavit podle typu plánu zákazníka nebo podle jiných kritérií.

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 });
		}
	},
};

Další podrobnosti o dostupných limitech najdete v Vlastní limity.

Chcete-li sledovat překročení limitů a další metriky napříč uživatelskými Workery, použijte Workers Analytics Engine. Pro podrobné protokolování a ladění nakonfigurujte Tail Worker k zachycení událostí z vašeho dispatch Workeru.