画像ツール一覧

Pub/Sub

Publish/Subscribe

アプリ開発

Pub/Subは、発行側が個々の受信者を直接指定せず、関心を登録した購読側へメッセージを届けるモデルです。分散システムでは、トピックやブローカーを介して非同期に連携する構成がよく使われます。

🐾 猫で例えると?

ソファーに横たわり、2匹とも顔をカメラへ向けているアメショと茶トラ
2匹への「おやつだよ」というお知らせに見立てる発行と購読

ソファーに横たわり、そろってこちらへ顔を向ける2匹。ここで飼い主が「おやつだよ」と知らせ、聞きたい猫がそれぞれ反応する場面を想像してみましょう。知らせることが発行(Publish)、通知を受けたいと登録することが購読(Subscribe)です。送り手が猫を一匹ずつ指名しなくても、関心のある受け手へ通知が届く点が対応します。

🐾 PR

💻 アプリ・Web開発における「Pub/Sub」とは?

直接APIを呼ぶ方式でも、適切なインターフェースで結合を弱められます。Pub/Subの特徴は、発行側が各購読者の処理完了を直接待たずに連携できる点です。その代わり、配信や処理の状態を別に管理する必要があります。

そこでPub/Subモデルを導入し、間に通知を仲介する「メッセージブローカー(イベントバス)」を挟みます。送信側(Pub)は「ユーザーが登録された」という事実だけをブローカーに投げ、受信側(Sub)は通知の種類を分ける「ユーザー登録トピック」を購読しておきます。これにより、送信側は誰が受信しているかを全く気にすることなく(疎結合)、後からメール送信機能やポイント付与機能(新しいSub)を追加しやすくなります。ただし、メッセージの形式や配信条件は送受信側で合わせる必要があります。

⚠️ Pub/Subの仕組みと注意点

順序、再配信、保存期間、配信先が停止していたときの扱いは製品と設定に依存します。順序を扱える仕組みもあるため「順序が必要なら必ず使えない」とは限りません。どの範囲で順序が保証されるかを確認します。

💡 イベント駆動アーキテクチャの基本

次のNode.js EventEmitterは、発行と購読を分ける考え方の例です。ただしemitは登録されたリスナーを同期的に呼び出します。ネットワーク越しの非同期配信、永続化、再送は実装していません。

// Node.jsでのシンプルなPub/Subの概念例
const EventEmitter = require('events');
const eventBus = new EventEmitter();

// サブスクライバー(受信側)の登録:トピックを購読
eventBus.on('user_registered', (data) => {
    console.log(`[メール送信] ${data.name}さんへ歓迎メールを送信`);
});

eventBus.on('user_registered', (data) => {
    console.log(`[ポイント付与] ${data.name}さんに初回ポイントを付与`);
});

// パブリッシャー(送信側)がイベントを発火
// 受信側が誰か、何個あるかは気にせず通知を投げるだけ
console.log('ユーザーが新規登録されました。');
eventBus.emit('user_registered', { name: 'Alice' });

分散したサービス間では、Google Cloud Pub/Sub、SNSとSQSの組み合わせ、Kafkaなどが選択肢になります。ただしキューの競合する受信者と、複数購読への配信は同じではありません。名前だけで置き換えず、配信モデルを確認します。

🛠️ Pub/Subを賢く使うためのポイント

発行したメッセージが届くまでの状態と、受信後の失敗の扱いを確認します。

飼い主が「おやつ(Pub)」というイベントを発火させた時、アメショは凄まじい圧で迫り、茶トラはゴロンゴロンとお腹を見せてアピールします。同じメッセージを受け取っても、受信側のシステム(猫)がそれぞれ異なる処理を選べるのがPub/Subの特徴です。追加する受信側についても、同じ通知を繰り返し受けた場合の動作を確認しておきましょう。