Service bindings(サービスバインディング)を使うと、公開 URL を経由せずに、ある Worker から別の Worker を呼び出せます。Service binding により、Worker A は Worker B のメソッドを呼び出すか、Worker A からのリクエストを Worker B に転送できます。
Service bindings は、マイクロサービスやサービス指向アーキテクチャが持つ関心の分離を、設定の手間、性能オーバーヘッド、RPC プロトコルの学習なしに提供します。
- 高速です。 Service bindings を使うと、オーバーヘッドや追加のレイテンシはありません。デフォルトでは、両方の Worker が同じ Cloudflare サーバーの同じスレッドで実行されます。Smart Placement を有効にすると、各 Worker は全体の性能に最適な場所で実行されます。
- HTTP だけではありません。 Worker A は、Worker B から直接呼び出せるメソッドを公開できます。サービス間の通信は、JavaScript のメソッドとクラスを書くだけで済みます。
- コストは増えません。 機能を複数の Worker に分割しても、追加コストは発生しません。Service bindings の料金 を参照してください。
Service bindings は、次の用途でよく使います。
- 複数の Worker に共有の内部サービスを提供する。 たとえば、認証サービスを独立した Worker としてデプロイし、任意の数の別 Worker から Service bindings で通信できます。
- サービスをパブリックインターネットから隔離する。 パブリックインターネットからは到達できず、別の Worker が宣言した明示的な Service binding 経由でのみ到達できる Worker をデプロイできます。
- チームが独立してコードをデプロイできるようにする。 チーム A は独自のリリーススケジュールで Worker をデプロイし、チーム B は別途デプロイできます。
Service binding は、呼び出し側(リクエストを開始したい Worker)の Wrangler 設定ファイル を変更して追加します。
たとえば、Worker A から Worker B を呼び出せるようにするには、Worker A の Wrangler 設定ファイル に次を追加します。
{
"services": [
{
"binding": "<BINDING_NAME>",
"service": "<WORKER_NAME>"
}
]
}[[services]]
binding = "<BINDING_NAME>"
service = "<WORKER_NAME>"binding:envオブジェクトに公開するキーの名前です。service: 通信先の Worker 名です。この Worker は、自分の Cloudflare アカウント上にある必要があります。
Worker B への Service binding を宣言した Worker A は、次の 2 通りで Worker B を呼び出せます。
- RPC では、自分で定義した関数呼び出しで Worker 間を通信します。例:
await env.BINDING_NAME.myMethod(arg1)。ほとんどの用途ではこちらを推奨します。Worker が他の Worker に公開する内部 API を作れます。 - HTTP では、他の Worker から
fetch()ハンドラー を呼び出し、Requestオブジェクトを送ってResponseオブジェクトを受け取ります。例:env.BINDING_NAME.fetch(request)。
この例では、RPC ベースの Service bindings に対応するため WorkerEntrypoint クラスを拡張 します。
まず、通信先の 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 B を呼び出す Worker を作成します。これを「Worker A」とします。Worker A は 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 のインスタンスを 2 つ起動します。各 Worker ごとに新しいターミナルを開き、npx wrangler@latest dev を実行します。
各 Worker は別々にデプロイします。
Service bindings API は非同期です。呼び出すメソッドは必ず await してください。Worker A が Service binding 経由で Worker B を呼び出し、Worker A が Worker B の完了を await しない場合、Worker B は途中で終了します。
Service binding 経由の RPC で Worker を呼び出すライフサイクルの詳細は、RPC Lifecycle を参照してください。
Service bindings はローカル開発に対応しています。各 Worker ごとに新しいターミナルを開き、該当ディレクトリで wrangler dev を使います。wrangler dev 実行時、その Worker の wrangler dev セッションを Wrangler が見つけられるかどうかで、service bindings は connected / not connected と表示されます。例:
$ 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 は、1 つのコマンドで複数の Worker を同時に動かすこともできます。試すには、次のように複数の -c フラグを渡します: wrangler dev -c wrangler.json -c ../other-worker/wrangler.json。最初の設定が プライマリ Worker として扱われ、通常どおり http://localhost:8787 で HTTP 公開されます。残りの設定ファイルは セカンダリ として扱われ、プライマリ Worker からの service binding 経由でのみアクセスできます。
Service bindings を使う Worker は、別々にデプロイします。
初めてデプロイする場合、対象の Worker(上の例では Worker B)を先にデプロイする必要があります。そうしないと、Worker A をデプロイしようとしたときに失敗します。Worker A はまだ存在しない Worker B へのバインディングを宣言しているためです。
既存の Worker を変更する場合、多くの場合は次の順で進めます。
- 既存の Worker A と互換性がある形で、まず Worker B の変更をデプロイします。たとえば、Worker B に新しいメソッドを追加します。
- 次に、Worker A の変更をデプロイします。たとえば、Worker A から Worker B の新しいメソッドを呼び出します。
- 最後に、使わなくなったコードを削除します。たとえば、以前使っていた Worker B のメソッドを削除します。
Smart Placement は、レイテンシが最小になる最適な場所に Worker を自動配置します。
Smart Placement と Service bindings を組み合わせて、Worker を 2 つのサービスに分割できます。
詳細は Smart Placement のドキュメント を参照してください。
Service bindings には、次の制限があります。
- Service binding 経由の各リクエストは、サブリクエスト制限 にカウントされます。
- 1 回のリクエストで呼び出せる Worker は最大 32 回です。Service binding の呼び出しもこの制限にカウントされます。以降の呼び出しは例外をスローします。
- Service binding の呼び出しは、同時オープン接続数の制限 にはカウントされません。