コンテンツにスキップ
タイプアンロック
ステージ本番環境
難易度中程度
ジョブストリームを共有
対象バックエンド開発者
対象開発チーム
サービスパイプ
サービスExec
Hoody の利点HTTP ネイティブ
Hoody の利点デフォルトでマルチプレイヤー
タイプアンロック
ステージ本番環境
難易度中程度
ジョブストリームを共有
対象バックエンド開発者
対象開発チーム
サービスパイプ
サービスExec
Hoody の利点HTTP ネイティブ
Hoody の利点デフォルトでマルチプレイヤー
タイプアンロック
ステージ本番環境
難易度中程度
ジョブストリームを共有
対象バックエンド開発者
対象開発チーム
サービスパイプ
サービスExec
Hoody の利点HTTP ネイティブ
Hoody の利点デフォルトでマルチプレイヤー
タイプアンロック
ステージ本番環境
難易度中程度
ジョブストリームを共有
対象バックエンド開発者
対象開発チーム
サービスパイプ
サービスExec
Hoody の利点HTTP ネイティブ
Hoody の利点デフォルトでマルチプレイヤー
PIPE · HTTP ファンアウト

構築する必要のなかった Webhook ファンアウト

Stripe が ?n=12 付きでパイプパスにイベント本文を POST します。12 のサブスクライバーが同じパスを ?n=12 付きで GET します。パイプは全員が接続するまでメッセージを保持し、その後 12 人全員に同時にストリームします。ブローカーも、コンシューマーグループも、DLQ も不要です。

パイプ docs を読む

1 つの URL。12 のリーダー。接続ごとのバックプレッシャー。

Hoody Pipe はマルチレシーバーモードを持つ HTTP ストリーミングです。送信者と受信者の両方の URL に ?n=N を追加すると、パイプは N 個のリーダーが接続するまで待機し、その後本文を全員に同時にミラーリングします。遅いものは自分の接続を絞り、速いものは流れ続けます。

01STEP 01 · INTAKE

Stripe がパイプに POST

Stripe エンドポイントがイベント本文を /api/v1/pipe/billing?n=12 にそのまま転送します。パイプが 12 のレシーバーが集まるのを待つ間、接続はブロックされます。

02STEP 02 · ASSEMBLE

12 のサブスクライバーが接続

各サブスクライバーはコンテナ内の curl ループで、同じパスを ?n=12 付きで GET します。パイプは 12 番目のリーダーが接続するまで本文をメモリ内に保持します — オンディスクキューも、フラッシュするものもありません。

03STEP 03 · STREAM

ファンアウトして、忘れる

全員が接続したら、本文は 12 人全員に一度にストリームされます。遅いリーダーは自分のソケットにバックプレッシャーをかけ、他は進み続けます。最後のリーダーが切断すると、パイプはメッセージを忘れます。

stripe-webhook.sh
# Sender side — your Stripe webhook handler.
# Pipe holds the body until 12 readers are attached.
curl -X POST "https://api.hoody.com/api/v1/pipe/billing?n=12" \
  -H "Authorization: Bearer $HOODY_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary "@stripe-event.json"

# Receiver side — one of twelve subscriber containers.
# Same path, same n. Streams the event body when fan-out is ready.
curl -N "https://api.hoody.com/api/v1/pipe/billing?n=12" \
  -H "Authorization: Bearer $HOODY_TOKEN" | ./billing-handler.sh

# n must match on both ends — mismatch returns 400.
# Default n=1 is point-to-point. n=12 is fan-out for twelve.

同じ URL、同じクエリ文字列、両端共通。送信者の接続がブローカー、リーダーの接続がコンシューマーグループです。トピックがないため、バックプレッシャーはトピック単位ではなくソケット単位です — 1 つのインフライト本文と、それを引っ張る 12 のソケットがあるだけです。

サブスクライバーはプロセスのように出入りします

サブスクライバーを追加するのは、別のコンテナ内でもう 1 つの curl を実行するだけです。削除するのは curl を kill するだけです。ブローカー設定も、コンシューマーグループのリバランスも、ドレインする DLQ もありません — クラスタートポロジーはまさに今動いているプロセスそのものです。

subscribers diff · 過去 5 分リバランス不要
  • + ADDED
    WHKAUD
    新しいコンテナ 2 つを起動
  • − REMOVED
    MIX
    コンテナを kill、curl が終了
  • = STABLE
    BILANLLOGFRDSUCSLACRMCDNNOT
    依然として同じ n=12 パスにいる

パイプは誰がサブスクライブしているかを追跡しません。イベントごとに n 個の接続を待つだけです。両端で n をバンプすると、次のイベントは新しい人数を待ちます。メンバーシップが存在しないため、破損するメンバーシップ状態もありません。

もう運用しなくていいもの

下のすべての行は、ブローカーがプロトコルそのものになると消える作業のカテゴリーです。プロビジョニングするインフラも、学ぶ抽象化もなく — ただ curl と ?n だけ。

  • プロビジョニングするキューはない

    SQS も、Kafka クラスターも、RabbitMQ エクスチェンジもありません。パイプがキューであり、一度に 1 メッセージのために生きています。

  • コンシューマーグループの管理は不要

    オフセットも、コミットも、リバランスもありません。パイプは n のソケットが接続するまで本文を保持します — それが調整モデルのすべてです。

  • ドレインする DLQ は不要

    送信者が n のリーダーが揃わずに切断した場合、パイプはタイムアウト (5 分 TTL) し、Stripe がリトライします。世話するポイズンメッセージのバケットはありません。

  • 言語ごとの SDK は不要

    サブスクライバーは curl ループ。送信者は curl。プロトコルは HTTP。URL を叩けるものなら何でもクラスターに参加できます。

  • ソケットごとのバックプレッシャー

    遅いリーダーは自分の接続を絞ります。他の 11 はフルスピードでストリームし続けます。フリート全体にわたるヘッドオブラインブロッキングはありません。

  • デフォルトで忘れっぽい

    本文は最後のリーダーが切断した瞬間に消えます。設定する保持ポリシーも、スケジュールするログ圧縮も、書く GDPR の delete-on-request ジョブもありません。

12 のサブスクライバー、1 つの URL、ブローカーなし。

下にあるブローカーは、HTTP ファンアウトがクエリパラメーターになる前にインストールしていたものです。右側はそれらを置き換えるもの — 1 つのパス、1 つの n、そして自分たちがクラスターであることを知らない 12 の curl プロセスです。

もう実行しないもの
  • AWS Lambda + SQS/SNS
  • Apache Kafka
  • RabbitMQ exchanges
  • カスタム Webhook ルーター
代わりに呼び出すもの
POST /api/v1/pipe/billing?n=12

12 のレシーバーが同じパスを同じ n で GET します。パイプがブローカーであり — 最後のリーダーが切断した瞬間にメッセージを忘れます。

ファンアウトセクションを読む

これが置き換えるもの

Webhook を N 個のコンシューマーにブロードキャストするためにこれらのいずれかに手を伸ばすなら、パイプモデルは 2 回の curl 呼び出しで同じ仕事をします — 片側に送信者、もう片側に受信者。

  • AWS Lambda + SQS/SNSトピックごとのブローカー、サブスクライバーごとの IAM
  • Apache Kafkaクラスター、ZooKeeper/KRaft、コンシューマーグループ
  • RabbitMQ exchangesバインディング、vhosts、環境ごとの管理 UI
  • カスタム Webhook ルーターメンテするサービス、発明するリトライ
  • Pub/Sub サービスメッセージごとの課金、GCP/AWS ロックイン
  • HTTP ファンアウトプラグインスタックごとのゲートウェイプラグイン、バックプレッシャーなし

1 スプリントかけて書いていたファンアウトが、今やクエリパラメーターです。?n=12 を追加して、出荷してください。

パイプ docs を読む

他のユースケースを読む