← Cloudflare Workers / workers / runtime-apis / bindings
Service bindings
О service bindings
Service bindings позволяют одному Worker обращаться к другому, минуя публично доступный URL. Service binding позволяет Worker A вызвать метод Worker B или переслать запрос от Worker A к Worker B.
Service bindings обеспечивают такое же разделение ответственности, как микросервисная или сервис-ориентированная архитектура, но без сложной настройки, потерь производительности и необходимости изучать протоколы RPC.
- Service bindings работают быстро. При использовании Service Bindings отсутствуют дополнительные накладные расходы и задержки. По умолчанию оба Worker выполняются в одном потоке одного и того же сервера Cloudflare. А если включить Smart Placement, каждый Worker выполняется в оптимальном месте для общей производительности.
- Service bindings не ограничены протоколом HTTP. Worker A может предоставлять методы, которые Worker B может вызывать напрямую. Для взаимодействия между сервисами достаточно написать методы и классы JavaScript.
- Service bindings не увеличивают расходы. Вы можете разделить функциональность на несколько Workers без дополнительных затрат. Подробнее о тарификация Service Bindings.
Service bindings обычно используются для:
- Предоставьте общий внутренний сервис нескольким Workers. Например, вы можете развернуть сервис аутентификации как отдельный Worker, а затем обращаться к нему из любого числа других Workers через Service bindings.
- Изоляция сервисов от публичного интернета. Вы можете развернуть Worker, недоступный через публичный интернет, к которому можно обратиться только через явный Service Binding, объявленный другим Worker.
- Позволяет командам развёртывать код независимо друг от друга. Команда A может развёртывать свой Worker по собственному графику релизов, а команда B может развёртывать свой Worker отдельно.
Конфигурация
Вы добавляете привязку Service binding, изменив конфигурационный файл Wrangler вызывающей стороны: Worker, для которого нужно разрешить инициировать запросы.
Например, если вы хотите, чтобы Worker A мог вызывать Worker B, добавьте следующее в конфигурационный файл Wrangler для Worker A:
{
"services": [
{
"binding": "<BINDING_NAME>",
"service": "<WORKER_NAME>"
}
]
}[[services]]
binding = "<BINDING_NAME>"
service = "<WORKER_NAME>"binding: Имя ключа, который нужно предоставить вenvобъект.service: Имя целевого Worker, с которым нужно взаимодействовать. Этот Worker должен находиться в вашем аккаунте Cloudflare.
Интерфейсы
Worker A, у которого объявлена привязка службы к Worker B, может вызывать Worker B двумя разными способами:
- RPC позволяет обмениваться данными между Workers с помощью вызовов функций, которые вы определяете сами. Например,
await env.BINDING_NAME.myMethod(arg1). Это рекомендуется для большинства сценариев использования и позволяет создавать собственные внутренние API, которые ваш Worker предоставляет другим Workers. - HTTP позволяет обмениваться данными между Workers путём вызова
fetch()обработчик от других Workers, отправляяRequestобъекты и получениеResponseобъекты обратно. Например,env.BINDING_NAME.fetch(request).
Пример: создайте свой первый Service Binding с помощью RPC
Этот пример расширяет WorkerEntrypoint класс для поддержки привязок Service на основе RPC.
Сначала создайте Worker, с которым нужно взаимодействовать. Назовем его "Worker B". Worker B предоставляет публичный метод, add(a, b):
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "worker_b",
"main": "./src/workerB.js"
}"$schema" = "./node_modules/wrangler/config-schema.json"
name = "worker_b"
main = "./src/workerB.js"import { WorkerEntrypoint } from "cloudflare:workers";
export default class WorkerB extends WorkerEntrypoint {
// Currently, entrypoints without a named handler are not supported
async fetch() {
return new Response(null, { status: 404 });
}
async add(a, b) {
return a + b;
}
}Затем создайте Worker, который будет вызывать Worker B. Назовём его «Worker A». Worker A объявляет привязку (binding) к Worker B, и именно она даёт ему право вызывать публичные методы Worker B.
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "worker_a",
"main": "./src/workerA.js",
"services": [
{
"binding": "WORKER_B",
"service": "worker_b"
}
]
}"$schema" = "./node_modules/wrangler/config-schema.json"
name = "worker_a"
main = "./src/workerA.js"
[[services]]
binding = "WORKER_B"
service = "worker_b"export default {
async fetch(request, env) {
const result = await env.WORKER_B.add(1, 2);
return new Response(result);
},
};Чтобы запускать Worker A и Worker B одновременно в локальной разработке, нужно запустить два экземпляра Wrangler в вашем терминале. Для каждого Worker откройте новый терминал и выполните npx wrangler@latest dev.
Каждый Worker развёртывается отдельно.
Жизненный цикл
The Service bindings API is asynchronous, you must await любой вызываемый вами метод. Если Worker A вызывает Worker B через Service binding и Worker A не дожидается завершения Worker B, Worker B будет завершён досрочно.
Подробнее о жизненном цикле вызова Worker через Service Binding по RPC см. в Жизненный цикл RPC документации.
Локальная разработка
Локальная разработка поддерживается для привязок Service. Для каждого Worker откройте новый терминал и используйте wrangler dev в соответствующем каталоге. При выполнении wrangler dev, service bindings будут отображаться как connected/not connected в зависимости от того, может ли Wrangler найти запущенный wrangler dev сессию для этого Worker. Например:
$ wrangler dev
...
Your worker has access to the following bindings:
- Services:
- SOME_OTHER_WORKER: some-other-worker [connected]
- ANOTHER_WORKER: another-worker [not connected]Wrangler также поддерживает запуск нескольких Workers одной командой. Чтобы попробовать, передайте несколько -c флаги в Wrangler, например так: wrangler dev -c wrangler.json -c ../other-worker/wrangler.json. Первая конфигурация будет рассматриваться как основной worker, который будет доступен по HTTP как обычно по адресу http://localhost:8787. Остальные файлы конфигурации будут рассматриваться как вторичный и будет доступен только через service binding из основного worker.
Развёртывание
Workers, использующие Service bindings, развёртываются отдельно.
На старте, при первом развертывании, это означает, что целевой Worker (Worker B в приведенных выше примерах) нужно развернуть раньше, чем Worker A. Иначе при попытке развернуть Worker A развертывание завершится ошибкой, поскольку Worker A объявляет binding на Worker B, который еще не существует.
При внесении изменений в существующие Workers в большинстве случаев следует:
- Сначала разверните изменения в Worker B так, чтобы они были совместимы с существующим Worker A. Например, добавьте новый метод в Worker B.
- Затем разверните изменения в Worker A. Например, вызовите новый метод Worker B из Worker A.
- Наконец, удалите весь неиспользуемый код. Например, удалите ранее использовавшийся метод в Worker B.
Smart Placement
Smart Placement автоматически размещает ваш Worker в оптимальном месте, минимизирующем задержку.
Smart Placement можно использовать вместе с Service bindings, чтобы разделить Worker на два сервиса:
См. документация о Smart Placement подробнее.
Лимиты
Service bindings имеют следующие ограничения:
- Каждый запрос к Worker через Service binding учитывается в вашем ограничение на подзапросы.
- На один запрос приходится не более 32 вызовов Worker, и каждый вызов через Service binding учитывается в этом лимите. Последующие вызовы вызовут исключение.
- Вызов service binding не учитывается в лимиты на количество одновременных открытых соединений