Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

複数の Web サーバーへリクエストを振り分ける

Workers KV にルーティングデータを保存し、Workers で複数の Web サーバーへリクエストを振り分けます

最終更新 Markdown で表示Agent セットアップ

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 の段階的デプロイ を参照してください。

Workers KV でリクエストを振り分ける

この例では、マルチテナントの e コマースアプリケーションを Cloudflare Workers 上に構築します。各ストアフロントは別テナントで、それぞれ独自の外部 Web サーバーを持ちます。 Cloudflare Worker は、すべてのストアフロント向けのリクエストを受け取り、ストアフロント ID に応じて正しいオリジン Web サーバーへ振り分けます。

説明を簡単にするため、ストアフロントはパス要素のストアフロント ID で識別します。ストアフロントの URL パターンは https://<WORKER_HOSTNAME>/<STOREFRONT_ID>/... です。実運用では、サブドメインでストアフロントを識別する方がよい場合があります。

index.tsjs

// 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 を検索します。 リクエストはオリジンサーバーへ転送され、レスポンスにはカスタムヘッダーを追加してからクライアントへ返します。

関連リソース

役に立ちましたか?