Workers KV にルーティングデータを保存し、Workers で複数の Web サーバーへリクエストを振り分けるのは、Workers KV の理想的なユースケースです。ルーティングのワークロードは読み取り量が多いことがあり、Workers KV の低レイテンシな読み取りにより、ルーティング判断をすばやく効率よく行えます。
ルーティングは、1 つの Cloudflare Worker アプリケーションに届いたリクエストを、パス、ホスト名、その他のリクエスト属性に基づいて、異なる Web サーバーへ振り分けるときに役立ちます。
シングルテナントのアプリケーションでは、業務ドメインに基づいてリクエストを各オリジンサーバーへ振り分けられます(例: /admin へのリクエストは管理サーバーへ、/store はストアフロントサーバーへ、/api は API サーバーへ)。
マルチテナントのアプリケーションでは、リクエストをテナントごとのオリジンリソースへ振り分けられます(例: tenantA.your-worker-hostname.com へのリクエストは Tenant A のサーバーへ、tenantB.your-worker-hostname.com は Tenant B のサーバーへ)。
ルーティングは、外部アプリケーション向けの A/B テスト、カナリアデプロイ、ブルーグリーンデプロイ ↗ の実装にも使えます。 Cloudflare Workers 上に完全に構築したアプリケーションのカナリアデプロイやブルーグリーンデプロイを実装する場合は、Workers の段階的デプロイ を参照してください。
この例では、マルチテナントの e コマースアプリケーションを Cloudflare Workers 上に構築します。各ストアフロントは別テナントで、それぞれ独自の外部 Web サーバーを持ちます。 Cloudflare Worker は、すべてのストアフロント向けのリクエストを受け取り、ストアフロント ID に応じて正しいオリジン Web サーバーへ振り分けます。
説明を簡単にするため、ストアフロントはパス要素のストアフロント ID で識別します。ストアフロントの URL パターンは https://<WORKER_HOSTNAME>/<STOREFRONT_ID>/... です。実運用では、サブドメインでストアフロントを識別する方がよい場合があります。
// Example routing data stored in Workers KV:
// Key: "storefrontA" | Value: {"origin": "https://storefrontA-server.example.com"}
// Key: "storefrontB" | Value: {"origin": "https://storefrontB-server.example.com"}
interface Env {
ROUTING_CONFIG: KVNamespace;
}
export default {
async fetch(request, env, ctx) {
// Parse the URL to extract the storefront ID from the path
const url = new URL(request.url);
const pathParts = url.pathname.split('/').filter(part => part !== '');
// Check if a storefront ID is provided in the path, otherwise return 400
if (pathParts.length === 0) {
return new Response('Welcome to our multi-tenant platform. Please specify a storefront ID in the URL path.', {
status: 400,
headers: { 'Content-Type': 'text/plain' }
});
}
// Extract the storefront ID from the first path segment
const storefrontId = pathParts[0];
try {
// Look up the storefront configuration in KV using env.ROUTING_CONFIG
const storefrontConfig = await env.ROUTING_CONFIG.get<{
origin: string;
}>(storefrontId, {type: "json"});
// If no configuration is found, return a 404
if (!storefrontConfig) {
return new Response(`Storefront "${storefrontId}" not found.`, {
status: 404,
headers: { 'Content-Type': 'text/plain' }
});
}
// Construct the new URL for the origin server
// Remove the storefront ID from the path when forwarding
const newPathname = '/' + pathParts.slice(1).join('/');
const originUrl = new URL(newPathname, storefrontConfig.origin);
originUrl.search = url.search;
// Create a new request to the origin server
const originRequest = new Request(originUrl, {
method: request.method,
headers: request.headers,
body: request.body,
redirect: 'follow'
});
// Send the request to the origin server
const response = await fetch(originRequest);
console.log(response.status)
// Clone the response and add a custom header
const modifiedResponse = new Response(response.body, response);
modifiedResponse.headers.set('X-Served-By', 'Cloudflare Worker');
modifiedResponse.headers.set('X-Storefront-ID', storefrontId);
return modifiedResponse;
} catch (error) {
// Handle any errors
console.error(`Error processing request for storefront ${storefrontId}:`, error);
return new Response('An error occurred while processing your request.', {
status: 500,
headers: { 'Content-Type': 'text/plain' }
});
}
}
} satisfies ExportedHandler<Env>;{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "<ENTER_WORKER_NAME>",
"main": "src/index.ts",
"compatibility_date": "2025-03-03",
"observability": {
"enabled": true
},
"kv_namespaces": [
{
"binding": "ROUTING_CONFIG",
"id": "<YOUR_BINDING_ID>"
}
]
}この例では、Cloudflare Worker がリクエストを受け取り、URL パスからストアフロント ID を取り出します。
ストアフロント ID を使い、get() メソッドで Workers KV からオリジンサーバーの URL を検索します。
リクエストはオリジンサーバーへ転送され、レスポンスにはカスタムヘッダーを追加してからクライアントへ返します。