コンテンツにスキップ
タイプアンロック
ステージ本番環境
難易度中程度
ジョブストリームを共有
対象バックエンド開発者
対象開発チーム
サービスパイプ
サービスコンテナ
Hoody の利点HTTP ネイティブ
Hoody の利点コンテナ経済学
タイプアンロック
ステージ本番環境
難易度中程度
ジョブストリームを共有
対象バックエンド開発者
対象開発チーム
サービスパイプ
サービスコンテナ
Hoody の利点HTTP ネイティブ
Hoody の利点コンテナ経済学
タイプアンロック
ステージ本番環境
難易度中程度
ジョブストリームを共有
対象バックエンド開発者
対象開発チーム
サービスパイプ
サービスコンテナ
Hoody の利点HTTP ネイティブ
Hoody の利点コンテナ経済学
タイプアンロック
ステージ本番環境
難易度中程度
ジョブストリームを共有
対象バックエンド開発者
対象開発チーム
サービスパイプ
サービスコンテナ
Hoody の利点HTTP ネイティブ
Hoody の利点コンテナ経済学
パイプ · コンテナ間通信

ブローカーなしのコンテナ間 IPC

サービス A が出力をパスにパイプします。サービス B が同じパスから受け取ります。パイプは 2 つのコンテナの間でリアルタイムにバイトをルーティング。Redis なし、コンシューマーグループなし、面倒を見るブローカーデーモンなし。

パイプドキュメントを読む

パイプがブローカーを置き換えるしくみ

2 つの HTTP 動詞と 1 つのパス。どちらの側が先に接続しても構いません。パイプは相手を最大 5 分待ち、その後バイトを通します。キューも、オフセットも、グループもありません。

01 · HANDSHAKE

どちらの側でも先に接続できる

プロデューサーがオフライン? コンシューマーが GET して待ちます。コンシューマーがオフライン? プロデューサーが PUT して待ちます。パイプは相手が現れるまで最大 5 分間接続を保持します。

02 · BACKPRESSURE

TCP 接続がキュー

コンシューマーが遅いとき、カーネルがプロデューサーのストリームを遅らせます。監視するキューの深さも、調整するハイウォーターマークもありません。ソケットがバッファです。

03 · STATELESS

配信後はメッセージを忘れる

正直なトレードオフ:何も永続化されません。永続的なキューイングが必要なら向いていません。コンテナ間の高速ファンアウトには、ブローカーがただ消えました。

producer.sh · consumer.sh
# Container A — producer streams jobs to the pipe
service-a | curl -T - https://api.hoody.com/api/v1/pipe/jobs

# Container B — consumer reads from the same path
curl https://api.hoody.com/api/v1/pipe/jobs | service-b

# Either side can connect first.
# The pipe holds the connection up to 5 minutes
# until the counterpart arrives, then streams through.

PUT (または POST) で送信。GET で受信。バイトはどこのディスクにも着地しません — プロデューサーからコンシューマーまでワイヤーを渡り、パイプが飛行中に転送します。

3 番目のリーダーを追加。次は 4 番目。

ロガーやメトリクスコレクターが同じイベントを必要とする場合は、?n を上げて curl を 1 つ加えるだけです。ブローカー設定も、コンシューマーグループも、ローテーションする認証シークレットもありません。新しいリーダーは単に存在するだけです。

pipe/jobs · readers?n=4 · 全件ファンアウト
  • + ADDED
    consumer-aloggermetricsaudit
    curl ?n=4 — ファンアウトに参加
  • = STABLE
    producer
    service-a | curl -T - ?n=4
  • − REMOVED
    redisconsumer-group.ymlbroker.conf
    ブローカーなし、設定なし

1 人の遅いリーダーはプロデューサーにバックプレッシャーをかけますが、他のリーダーはブロックしません。1 つのパスにつき最大 256 リーダーまで。

ブローカーが奪っていたもの、URL が返してくれるもの

ブローカーは 2 つのコンテナが直接話せなかったから存在していました。パイプがあれば話せます。ブローカーが追加した認証、クライアント、運用 — そのすべてが消えます。

  • 運用するデーモンなし

    デプロイ、監視、アップグレードするものはありません。パイプがプラットフォームで、URL が唯一の API です。

  • ブローカー資格情報ではなく Bearer 認証

    Hoody トークン 1 つを、プロジェクトごとにスコープ。ブローカーごとのユーザー名、パスワード、ACL ファイルはありません。

  • 同じワイヤー、どんな言語でも

    HTTP を話すものなら何でもプロデュースまたはコンシュームできます — bash、Python、Go、スマホ、ブラウザ。クライアントライブラリ不要。

  • 永続化されたステートなし

    メッセージは飛行中に存在し、静止状態にはなりません。埋まるディスクも、保管ポリシーも、キューに入ったデータについての GDPR の問いもありません。

  • バックプレッシャーがプロトコル

    最も遅いコンシューマーが遅れると、TCP がプロデューサーを減速させます。遅延ダッシュボードがないのは遅延がないから — あるのはストリームレートだけです。

  • コンテナは結合しないまま

    プロデューサーとコンシューマーはお互いの IP を知りません。共有するのは URL だけ。配線を変えずにどちらかを別のホストに移せます。

ブローカーが URL。URL がブローカー。

中間レイヤーが消えます。資格情報、クライアント、ランブック付きのステートフルデーモンだったものが、いまやパスです。アーキテクチャ図のボックスが 1 つ減ります。

前はあった
  • redis cluster認証、レプリカ、フェイルオーバー
  • consumer-group.ymlオフセット、パーティション
  • サービスごとのブローカー SDK言語ごとのクライアントライブラリ
今もある
/api/v1/pipe/jobs

1 つの URL、1 つの curl、1 つの HTTP 動詞

パイプドキュメントを読む

これが置き換えるもの

1 つのコンテナが別のコンテナにバイトを渡す必要があるとき、チームが手を伸ばすインフラ群。どれもデーモン、設定、オンコールローテーションを足します。パイプはそのどれも要求しません。

  • Redis pub/subデーモン、認証、言語ごとのクライアント
  • RabbitMQ飛行中のバイトのために運用するクラスタ
  • NATSもう 1 つのプロトコル、もう 1 つのサイドカー
  • ZeroMQサービスごとのライブラリ、URL なし
  • カスタムルーティングデーモン生かし続けるべきカスタムサービス
  • gRPC ストリーミングサービススキーマ、コード生成、相互 TLS のオーバーヘッド
  • Apache Kafka ブローカー保持しないメッセージのためのストレージレイヤー

2 つのコンテナの間で会話するために Redis を立てますか? それとも URL を共有しますか。

パイプ API を見る

他のユースケースを読む