メインコンテンツへスキップ
三田工場 技術サイト
Pub/Subモデルとトピックの仕組み

Pub/Subモデルとトピックの仕組み

HowTo8分で読めます

このシリーズ: 全5回

  1. 第1回: MQTTとは?IoT時代の「伝言板」を初心者向けに解説
  2. 第2回: Pub/Subモデルとトピックの仕組み ← 今ここ
  3. 第3回: 実践:Raspberry Piで設備監視システムを作る
  4. 第4回: 複数のRaspberry Piを中継機で束ねてOracle DBにデータを送る
  5. 第5回: MQTTで双方向通信!Oracleのデータを子機に配信する

はじめに

前回の記事では、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で設備監視システムを作る

実際にRaspberry PiとMosquittoを使って、 設備監視システムを構築する手順を解説します。

関連記事