
Pub/Subモデルとトピックの仕組み
HowTo8分で読めます
このシリーズ: 全5回
はじめに
前回の記事では、MQTTの基本概念を「伝言板」に例えて説明しました。
今回は、MQTTの心臓部である:
- Pub/Sub(パブサブ)モデル
- トピック
について、図解で詳しく解説します。
Pub/Subモデルとは?
従来の通信:電話方式
text
┌─────────┐ ┌─────────┐
│ 送信者 │ ←────────────────→ │ 受信者 │
└─────────┘ 直接通話 └─────────┘
問題:
・相手が不在だと通信できない
・1対1しかできない
・相手の電話番号を知っている必要があるPub/Sub:掲示板方式
text
┌─────────┐ ┌─────────┐
│ Publisher│ │Subscriber│
│ (発信者) │ │ (購読者) │
└────┬─────┘ └────┬─────┘
│ │
│ ① メッセージを投稿 │
▼ │
┌─────────────────────────────────────────┐ │
│ │ │
│ 📋 掲示板 │ │
│ (Broker) │←───┘
│ │ ② 興味のある
│ ┌─────────────────────────────────┐ │ カテゴリを登録
│ │ 🏭 工場/センサー/温度 │ │
│ │ → 「25.5度」 │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────┐ │
│ │ 🏠 家/リビング/照明 │ │ ③ 新着があれば
│ │ → 「ON」 │ │ ─────→ 自動通知
│ └─────────────────────────────────┘ │
│ │
└─────────────────────────────────────────┘Pub/Subのメリット
text
┌─────────────────────────────────────────────────────────┐
│ Pub/Subの利点 │
├─────────────────────────────────────────────────────────┤
│ │
│ ✅ 疎結合(そけつごう) │
│ → 送信者と受信者がお互いを知らなくてOK │
│ │
│ ✅ スケーラブル │
│ → 受信者が100人でも1000人でも、送信者は1回送るだけ │
│ │
│ ✅ 非同期 │
│ → 受信者がオフラインでも、後で受け取れる │
│ │
│ ✅ フィルタリング │
│ → 興味のあるメッセージだけ受け取れる │
│ │
└─────────────────────────────────────────────────────────┘トピック(Topic)とは?
トピックは、メッセージを分類するための「住所」のようなものです。
トピックの書き方
text
┌─────────────────────────────────────────────────────────┐
│ トピックの構造 │
├─────────────────────────────────────────────────────────┤
│ │
│ factory/line1/sensor/temperature │
│ ─────── ───── ────── ─────────── │
│ │ │ │ │ │
│ │ │ │ └─ 温度 │
│ │ │ └─────────── センサー │
│ │ └─────────────────── ライン1 │
│ └─────────────────────────── 工場 │
│ │
│ ※ 「/」で階層を区切る(フォルダのような構造) │
│ │
└─────────────────────────────────────────────────────────┘トピックの例
text
家の場合:
┌─────────────────────────────────────────┐
│ home/ │
│ ├── livingroom/ │
│ │ ├── temperature → 「26.5」 │
│ │ ├── humidity → 「45%」 │
│ │ └── light → 「ON」 │
│ ├── bedroom/ │
│ │ ├── temperature → 「24.0」 │
│ │ └── aircon → 「冷房」 │
│ └── kitchen/ │
│ └── smoke → 「正常」 │
└─────────────────────────────────────────┘
工場の場合:
┌─────────────────────────────────────────┐
│ equipment/ │
│ └── status/ │
│ ├── EQ001 → 「稼働中」 │
│ ├── EQ002 → 「停止」 │
│ └── EQ003 → 「異常」 │
└─────────────────────────────────────────┘ワイルドカード:まとめて購読
「+」:1階層だけ
text
購読: home/+/temperature
┌─────────────────────────────────────────┐
│ │
│ home/livingroom/temperature ✅ 受信 │
│ home/bedroom/temperature ✅ 受信 │
│ home/kitchen/temperature ✅ 受信 │
│ │
│ home/livingroom/humidity ❌ 対象外 │
│ home/bedroom/light ❌ 対象外 │
│ │
└─────────────────────────────────────────┘
「+」= どの部屋でもOK、でも「temperature」だけ「#」:すべての階層
text
購読: home/livingroom/#
┌─────────────────────────────────────────┐
│ │
│ home/livingroom/temperature ✅ 受信 │
│ home/livingroom/humidity ✅ 受信 │
│ home/livingroom/light ✅ 受信 │
│ home/livingroom/ac/status ✅ 受信 │
│ │
│ home/bedroom/temperature ❌ 対象外 │
│ home/kitchen/smoke ❌ 対象外 │
│ │
└─────────────────────────────────────────┘
「#」= リビングの情報ならなんでもOK比較表
| ワイルドカード | 意味 | 例 |
|---|---|---|
+ |
1階層のみ | sensor/+/temp → sensor/A/temp, sensor/B/temp |
# |
以降すべて | sensor/# → sensor/A/temp, sensor/B/humidity... |
実際の動きを見てみよう
シナリオ:工場の設備監視
text
時刻 10:00:00
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
① 設備EQ001のセンサーがデータを送信(Publish)
┌─────────────┐ ┌──────────────┐
│ EQ001 │ ───────→ │ │
│ センサー │ Publish │ Broker │
└─────────────┘ │ (Mosquitto) │
│ │
トピック: equipment/status/EQ001 │
データ: {"status": 1, "name": "稼働中"} │
└──────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
② Brokerが購読者にメッセージを配信
┌──────────────┐
│ │
│ Broker │
│ │
└──────┬───────┘
│
┌────────────────────┼────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ 監視モニター │ │ データベース │ │ アラートシステム │
│ │ │ │ │ │
│ equipment/# │ │ equipment/status/#│ │ equipment/+/alert│
│ を購読中 │ │ を購読中 │ │ を購読中 │
└──────────────────┘ └──────────────────┘ └──────────────────┘
✅ 受信 ✅ 受信 ❌ 対象外
(alertトピックではない)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━なぜこの仕組みが便利なの?
例:新しい監視システムを追加したい場合
従来の方式(直接接続):
text
┌─────────┐ ┌─────────┐
│ センサー │ ──→ │ 旧システム│
└─────────┘ └─────────┘
新システムを追加するには...
・センサーの設定を変更
・新システムへの接続を追加
・テスト、動作確認...
→ センサー側の修正が必要!Pub/Sub方式:
text
┌─────────┐
┌──→ │ 旧システム│
┌─────────┐ │ └─────────┘
│ センサー │ → Broker ─┤
└─────────┘ │ ┌─────────┐
└──→ │ 新システム│ ← 購読するだけ!
└─────────┘
→ センサーは何も変更不要!
→ 新システムがBrokerを購読するだけ!今回のシステムでの使い方
text
┌─────────────────────────────────────────────────────────────┐
│ 設備状態監視システム │
├─────────────────────────────────────────────────────────────┤
│ │
│ Publisher(発信者) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Raspberry Pi │ │ Raspberry Pi │ │ Raspberry Pi │ │
│ │ カメラ1 │ │ カメラ2 │ │ カメラ3 │ │
│ │ EQ001 │ │ EQ002 │ │ EQ003 │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ │ Publish │ Publish │ Publish │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Mosquitto Broker (中継機) │ │
│ │ 192.168.32.213 │ │
│ │ │ │
│ │ トピック: equipment/status/# │ │
│ │ │ │
│ └─────────────────────────┬───────────────────────────┘ │
│ │ │
│ │ Subscribe │
│ ▼ │
│ Subscriber(購読者) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ MQTT-Oracle ブリッジ │ │
│ │ │ │
│ │ equipment/status/# を購読 │ │
│ │ → 受信したデータをOracleに保存 │ │
│ └─────────────────────────┬───────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Oracle Cloud Database │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘まとめ
| 概念 | 説明 | ポイント |
|---|---|---|
| Pub/Sub | 発行/購読モデル | 送信者と受信者が直接つながらない |
| Topic | メッセージの住所 | 階層構造で整理(factory/line/sensor) |
| + | 1階層ワイルドカード | sensor/+/temp |
| # | 全階層ワイルドカード | sensor/# |
| 疎結合 | ゆるいつながり | 追加・削除が簡単 |
次の記事
実際にRaspberry PiとMosquittoを使って、 設備監視システムを構築する手順を解説します。