← Cloudflare Workers KV / kv / examples
Маршрутизация запросов между различными веб-серверами
Использование Workers KV для хранения данных маршрутизации и распределения запросов между разными веб-серверами с помощью Workers является идеальным сценарием использования Workers KV. Такая нагрузка на маршрутизацию может создавать высокий объём операций чтения, и быстрые операции чтения Workers KV с низкой задержкой помогают принимать решения о маршрутизации быстро и эффективно.
Маршрутизация полезна, когда нужно направлять запросы, поступающие в одно приложение Cloudflare Worker, на разные веб-серверы в зависимости от пути запроса, хоста или других его атрибутов.
В однотенантных приложениях это можно использовать для маршрутизации запросов к разным серверам источника в зависимости от бизнес-домена (например, запросы к /admin направляется на административный сервер, /store направляется на сервер витрины, /api направляется на сервер API).
В мультитенантных приложениях запросы можно направлять к соответствующим ресурсам источника конкретного тенанта (например, запросы к tenantA.your-worker-hostname.com направляется на сервер для Tenant A, tenantB.your-worker-hostname.com направляется на сервер для Tenant B).
Маршрутизацию также можно использовать для реализации A/B тестирование, canary-развертывания, или сине-зелёные развёртывания ↗ для собственных внешних приложений. Если вы хотите реализовать canary или blue-green развёртывания приложений, полностью построенных на Cloudflare Workers, см. Workers gradual deployments.
Маршрутизация запросов с помощью Workers KV
В этом примере на Cloudflare Workers построено мультитенантное приложение электронной коммерции. Каждый интернет-магазин представляет собой отдельного тенанта и имеет собственный внешний веб-сервер. Наш Cloudflare Worker принимает все запросы для всех магазинов и направляет их на нужный веб-сервер источника в соответствии с идентификатором магазина.
Для простоты демонстрации витрина магазина будет идентифицироваться с помощью элемента пути, содержащего ID витрины, где
https://<WORKER_HOSTNAME>/<STOREFRONT_ID>/... это шаблон URL для витрины. В реальном сценарии вам может быть удобнее использовать поддомены для идентификации витрин.
// 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.
Этот идентификатор используется для поиска URL-адреса сервера источника в Workers KV с помощью get() метод.
Затем запрос перенаправляется на исходный сервер, а в ответ перед возвратом клиенту добавляются пользовательские заголовки.