INTEGRITY Документация

Placement

По умолчанию Workers и Pages Functions выполняться в дата-центре, ближайшем к месту получения запроса. Если ваш Worker обращается к серверной инфраструктуре, например к базам данных или API, может быть эффективнее запускать этот Worker ближе к серверной части, чем к конечному пользователю.

{
	"placement": {
		// Use one of the following options (mutually exclusive):
		"mode": "smart", // Cloudflare automatically places your Worker closest to the upstream with the most requests
		"region": "gcp:us-east4", // Explicit cloud region to run your Worker closest to - e.g. "gcp:us-east4" or "aws:us-east-1"
		"host": "db.example.com:5432", // A host to probe (TCP/layer 4) - e.g. a database host - and place your Worker closest to
		"hostname": "api.example.com", // A hostname to probe (HTTP/layer 7) - e.g. an API endpoint - and place your Worker closest to
	},
}
[placement]
mode = "smart"
region = "gcp:us-east4"
host = "db.example.com:5432"
hostname = "api.example.com"

Placement снижает общую задержку запроса к Worker за счёт минимизации задержки прохождения запросов между вашим Worker и бэкенд-сервисами. Это позволяет добиться задержки на уровне единиц миллисекунд при обращении к базам данных, API и другим сервисам, работающим в устаревшей облачной инфраструктуре.

Опция Подходит для Конфигурация
Smart Несколько бэкенд-сервисов или неизвестное расположение инфраструктуры mode = "smart"
Регион Единый бэкенд-сервис в известном облачном регионе region
Host Единый бэкенд-сервис вне крупного облачного провайдера host или hostname

Изучите размещение

Представим пользователя из Сиднея (Австралия), который обращается к приложению, работающему на Workers. Это приложение выполняет несколько циклов обмена данными с базой данных во Франкфурте (Германия).

Пользователь из Сиднея, Австралия, подключается к Worker в том же регионе, который затем делает несколько round trip к базе данных, расположенной во Франкфурте, Германия.

Задержка от нескольких обращений туда и обратно между Сиднеем и Франкфуртом накапливается. Если разместить Worker рядом с базой данных, Cloudflare сокращает общую длительность запроса.

Пользователь из Сиднея, Австралия, подключается к Worker во Франкфурте, Германия, который затем делает несколько round trip к базе данных, также расположенной во Франкфурте, Германия.

Включите Smart Placement

Smart Placement автоматически анализирует характер трафика вашего Worker и размещает его в оптимальном местоположении. Используйте Smart Placement, если:

Smart Placement включается для каждого Worker отдельно. После включения он анализирует длительность запроса Worker в разных точках присутствия Cloudflare на регулярной основе.

Для каждой возможной локации Smart Placement учитывает производительность Worker и сетевую задержку, добавляемую при пересылке запроса. Если какая-то локация оказывается значительно быстрее, запрос перенаправляется туда. В остальных случаях Worker выполняется в локации по умолчанию, ближайшей к запросу.

Smart Placement учитывает только те местоположения, где Worker уже выполнялся ранее. Он не может разместить ваш Worker там, куда обычно не поступает трафик.

Ознакомьтесь с ограничениями

Включить Smart Placement

Smart Placement доступен на всех тарифах Workers.

Настройка с помощью Wrangler

Добавьте следующее в файл конфигурации Wrangler:

{
	"placement": {
		"mode": "smart",
	},
}
[placement]
mode = "smart"

Smart Placement может анализировать ваш Worker до 15 минут после развёртывания.

Настройка в панели управления

  1. Перейдите в Workers & Pages.

    Перейдите в Workers & Pages ↗
  2. Выберите свой Worker.

  3. Перейдите в Настройки > Общее.

  4. В разделе Placement, выберите Smart.

Для принятия решения о размещении Smart Placement требуется стабильный трафик к Worker из нескольких местоположений. Анализ может занимать до 15 минут.

Проверка статуса размещения

Запросите статус размещения вашего Worker через Workers API:

curl -X GET https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/services/$WORKER_NAME \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" | jq .

Возможные состояния размещения:

Статус Описание
(отсутствует) Worker еще не анализировался. Он выполняется в расположении по умолчанию, ближайшем к запросу.
SUCCESS Worker был проанализирован и будет оптимизирован с помощью Smart Placement.
INSUFFICIENT_INVOCATIONS Worker не получил достаточно запросов из разных локаций для принятия решения о размещении.
UNSUPPORTED_APPLICATION Smart Placement сделал Worker медленнее и отменил размещение. Такое состояние встречается редко (менее чем для 1% Workers).

Просмотрите аналитику длительности запросов

После включения Smart Placement собираются данные о длительности запросов. Длительность запроса измеряется в дата-центре, ближайшем к конечному пользователю. По умолчанию 1% запросов не маршрутизируется через Smart Placement и служит базовым уровнем для сравнения.

Просмотр у вашего Worker аналитика длительности запроса чтобы оценить эффект от Smart Placement.

Проверьте cf-placement заголовок

Cloudflare добавляет cf-placement заголовок ко всем запросам, когда размещение включено. Используйте этот заголовок, чтобы проверить, был ли запрос маршрутизирован с помощью Smart Placement и где Worker обработал запрос.

Значение заголовка включает тип размещения и код аэропорта, указывающий на расположение дата-центра:

Настройка явных Placement Hints

Placement Hints позволяют явно указать, где выполняется ваш Worker. Используйте Placement Hints, если:

Примеры включают основную базу данных, виртуальную машину или кластер Kubernetes в определённом регионе. Сокращение задержки кругового пути на запрос с 20 до 30 миллисекунд до значения от 1 до 3 миллисекунд повышает скорость отклика.

Укажите облачный регион

Если ваша инфраструктура работает в AWS, GCP или Azure, задайте placement.region свойство, используя формат {provider}:{region}:

{
	"placement": {
		"region": "aws:us-east-1", // Explicit cloud region to run your Worker closest to - e.g. "gcp:us-east4" or "aws:us-east-1"
	},
}
[placement]
region = "aws:us-east-1"

Cloudflare сопоставляет указанный вами облачный регион с дата-центром, имеющим наименьшую задержку до этого региона. Cloudflare автоматически корректирует размещение с учётом обслуживания сети или изменений в ней, поэтому указывать резервные регионы не требуется.

Укажите конечную точку хоста

Если ваша инфраструктура развёрнута не у одного из крупных облачных провайдеров, вы можете указать конечную точку, которую Cloudflare сможет опросить. Cloudflare определит примерное местоположение внешнего хоста и разместит Workers в ближайшем регионе.

Задайте placement.host чтобы определить сервис уровня 4. Cloudflare измеряет задержку с помощью проверок TCP CONNECT и выбирает оптимальный дата-центр.

{
	"placement": {
		"host": "my_database_host.com:5432", // A host to probe (TCP/layer 4) - e.g. a database host - and place your Worker closest to
	},
}
[placement]
host = "my_database_host.com:5432"

Задайте placement.hostname чтобы определить сервис уровня 7. Cloudflare измеряет задержку с помощью проверок HTTP HEAD и выбирает оптимальный дата-центр.

{
	"placement": {
		"hostname": "my_api_server.com", // A hostname to probe (HTTP/layer 7) - e.g. an API endpoint - and place your Worker closest to
	},
}
[placement]
hostname = "my_api_server.com"

Зонды отправляются из публичных диапазонов IP-адресов, а не из диапазонов IP-адресов Cloudflare. Cloudflare регулярно перепроверяет расположение службы. Эти зонды предназначены для ресурсов с одним расположением и не работают корректно для широковещательных, anycast, многоадресных и реплицированных ресурсов.

Список поддерживаемых регионов

Placement Hints поддерживают идентификаторы регионов Amazon Web Services (AWS), Google Cloud Platform (GCP) и Microsoft Azure:

Провайдер Формат Примеры
AWS aws:{region} aws:us-east-1, aws:us-west-2, aws:eu-central-1
GCP gcp:{region} gcp:us-east4, gcp:europe-west1, gcp:asia-east1
Azure azure:{region} azure:westeurope, azure:eastus, azure:southeastasia

Полный список кодов регионов см. в Регионы AWS, Регионы GCP, или Регионы Azure.

Placement Behavior

Размещение Workers ведёт себя одинаково при использовании Smart Placement или Placement Hints. Ниже описано поведение, общее для обоих вариантов.

Ознакомьтесь с ограничениями

Следующие ограничения действуют как для Smart Placement, так и для Placement Hints:

cf-placement заголовок

Cloudflare добавляет cf-placement заголовок добавляется ко всем запросам, если включено размещение. Используйте этот заголовок, чтобы проверить, был ли запрос направлен с учётом размещения и где Worker обработал этот запрос.

Значение заголовка включает тип размещения и код аэропорта, указывающий на расположение дата-центра:

Несколько Workers

Если вы создаете full-stack приложения на Workers, разделяйте edge-логику (аутентификация, маршрутизация) и логику бэкенда (запросы к базе данных, вызовы API) на отдельные Workers. Используйте Service Bindings чтобы соединить их через типобезопасный RPC.

Smart Placement и Service Bindings

Включите размещение бэкенд-Worker, чтобы вызывать его ближе к базе данных, а edge Worker будет обрабатывать аутентификацию ближе к пользователю.

Пример: аутентификация на edge с размещённым бэкендом

В этом примере показаны два Worker:

{
	"name": "auth-worker",
	"main": "src/index.ts",
	"services": [{ "binding": "APP", "service": "app-worker" }],
}
name = "auth-worker"
main = "src/index.ts"

[[services]]
binding = "APP"
service = "app-worker"
auth-worker/src/index.ts
import { AppWorker } from "../app-worker/src/index";

interface Env {
	APP: Service<AppWorker>;
}

export default {
	async fetch(request: Request, env: Env): Promise<Response> {
		const authHeader = request.headers.get("Authorization");
		if (!authHeader?.startsWith("Bearer ")) {
			return new Response("Unauthorized", { status: 401 });
		}

		const userId = await validateToken(authHeader.slice(7));
		if (!userId) {
			return new Response("Invalid token", { status: 403 });
		}

		// Call the placed back-end Worker via RPC
		const data = await env.APP.getUser(userId);
		return Response.json(data);
	},
};

async function validateToken(token: string): Promise<string | null> {
	return token === "valid" ? "user-123" : null;
}
{
	"name": "app-worker",
	"main": "src/index.ts",
	"placement": {
		// Use one of the following options (mutually exclusive):
		// "mode": "smart", // Cloudflare automatically places your Worker closest to the upstream with the most requests
		"region": "aws:us-east-1", // Explicit cloud region to run your Worker closest to - e.g. "gcp:us-east4" or "aws:us-east-1"
		// "host": "db.example.com:5432", // A host to probe (TCP/layer 4) - e.g. a database host - and place your Worker closest to
		// "hostname": "api.example.com", // A hostname to probe (HTTP/layer 7) - e.g. an API endpoint - and place your Worker closest to
	},
}
name = "app-worker"
main = "src/index.ts"

[placement]
region = "aws:us-east-1"
app-worker/src/index.ts
import { WorkerEntrypoint } from "cloudflare:workers";

export default class AppWorker extends WorkerEntrypoint {
	async fetch() {
		return new Response(null, { status: 404 });
	}

	// Each method runs near your database - multiple queries stay fast
	async getUser(userId: string) {
		const user = await this.env.DB.prepare("SELECT * FROM users WHERE id = ?")
			.bind(userId)
			.first();
		return user;
	}

	async getUserListings(userId: string) {
		// Multiple round-trips to the DB are low-latency when placed nearby
		const user = await this.env.DB.prepare("SELECT * FROM users WHERE id = ?")
			.bind(userId)
			.first();
		const listings = await this.env.DB.prepare(
			"SELECT * FROM listings WHERE owner_id = ?",
		)
			.bind(userId)
			.all();
		const reviews = await this.env.DB.prepare(
			"SELECT * FROM reviews WHERE listing_id IN (SELECT id FROM listings WHERE owner_id = ?)",
		)
			.bind(userId)
			.all();

		return { user, listings: listings.results, reviews: reviews.results };
	}
}

auth-worker выполняется на периферии сети, чтобы быстро отклонять неавторизованные запросы. Прошедшие аутентификацию запросы пересылаются через RPC в app-worker, который выполняется рядом с вашей базой данных для быстрых запросов.

Durable Objects

Durable Objects обеспечивают автоматическое размещение без настройки. Запросы к встроенному в Durable Object База данных SQLite фактически являются нулевая задержка потому что вычисления выполняются в том же процессе, что и данные.

Выполняйте как можно больше работы внутри Durable Object и возвращайте единый составной результат, вместо того чтобы делать несколько обращений из своего Worker:

src/index.ts
import { DurableObject } from "cloudflare:workers";

type Session = { id: string; user_id: string; created_at: number };
type PromptHistory = {
	id: string;
	session_id: string;
	role: string;
	content: string;
};

export class AgentHistory extends DurableObject {
	async getSessionContext(sessionId: string) {
		// All queries execute with zero network latency — compute and data are colocated
		const session = this.ctx.storage.sql
			.exec<Session>("SELECT * FROM sessions WHERE id = ?", sessionId)
			.one();
		const prompts = this.ctx.storage.sql
			.exec<PromptHistory>(
				"SELECT * FROM prompt_history WHERE session_id = ? ORDER BY created_at",
				sessionId,
			)
			.toArray();

		return { session, prompts };
	}
}