手短にいうと

MQTT(Message Queuing Telemetry Transport)は、発行と購読にもとづく軽量なメッセージングのプロトコルで、回線が悪く、メモリーが少なく、電池を長持ちさせたい機器のために作られました。

1999 年に IBM の Andy Stanford-Clark と Arcom の Arlen Nipper が、石油パイプラインのテレメトリーを衛星で運ぶために作りました。条件は容赦のないものでした。帯域は高価で細く、回線は絶えず切れ、機器はきゃしゃでした。その制約がプロトコルのすべてを形づくっています。極小のヘッダー、長く保つ 1 本の接続、そして切断をメッセージを失わずに乗り切る力です。

いま MQTT は OASIS の標準であり、バージョン 3.1.1 はさらに国際規格 ISO/IEC 20922 としても採用されました。石油産業はとうに超え、スマートホーム、各種メーター、工作機械、自動車、医療機器がこれで動いています。

1 通あたりの最小の上乗せはわずか 2 バイトです。比べて HTTP のリクエストは、中身に入る前にヘッダーだけで数百バイトを使います。野外の機器が携帯回線で毎秒 1 回、気温を送るような場面では、この差が設計を決めます。

仕組み:発行、購読、そしてブローカー

HTTP ではクライアントが尋ね、サーバーが答えます。MQTT では誰も誰にも尋ねません。機器はトピックへメッセージを発行し、そのトピックを購読している全員が受け取ります。送り手は誰が読むのか、そもそも読む人がいるのかも知らず、受け手は誰が送ったのかを知りません。両者を結ぶのはトピックの名前だけです。

中央には必ずブローカーがいます。接続を保ち、購読の木を管理し、メッセージを配るサーバーです。これがなければこの仕組みは成り立ちません。「虚空へ送った」を「必要な全員へ届けた」に変えるのがブローカーです。

ブローカーの役目

  • 接続を受け入れて保ちます。同時に数千、途切れずに何年も。
  • 接続してきた相手を確かめます。ユーザー名とパスワード、証明書、あるいはトークンで。
  • 各クライアントに何を許すかを決めます。発行と購読の権限はトピック単位で与えます。
  • 発行されたメッセージを購読の木と照合し、その写しを配ります。
  • 状態を保ちます。最後に判明した値(retain)、不在のクライアント向けの待ち行列、未完了の確認応答。
  • 誰が生きているかを見張り、消えた相手の遺言を代わりに公開します。
ここから、設計時に織り込んでおくべきことが導かれます。ブローカーはすべてが一点に集まる唯一の場所です。ボトルネックであり、単一障害点であり、同時にシステムの様子を見るのに最適な場所でもあります。補助的な道具ではなく、データベースサーバーのように扱ってください。

送り手と受け手を切り離すのは技術的な細部ではなく、この仕組みの要そのものです。センサーを交換しても、受け手を 1 つ増やしても、脇に分析を足しても、何も書き直さずに済みます。全員が互いにではなく、トピックに向かって話しているからです。

トピックとワイルドカード

トピックは、斜線で区切られた階層の文字列です。事前の登録は要りません。新しいトピックへ発行すれば、その場で生まれます。

office/floor2/room14/temperature
office/floor2/room14/humidity
office/floor2/room15/temperature

購読では 2 つのワイルドカードで枝ごとまとめて拾えます:

記号意味拾える範囲
+ちょうど 1 階層office/floor2/+/temperature2 階のすべての部屋の気温
#その階層を含む以下すべてoffice/#オフィスのすべてのトピック

# は最後の階層でしか使えません。office/#/temperature は正しいフィルターではありません。トピックは大文字と小文字を区別し、office/floor2office/floor2/ は別のトピックです。

$ で始まるトピックはサーバー自身のために予約されています。多くはブローカーの統計を運ぶ $SYS です。ワイルドカードはそこには届きません# を購読しても $SYS は見えず、明示的なフィルターが要ります。

サービス品質:QoS 0、1、2

MQTT では、1 通ごとにどれだけ手間をかけて届けるかを選べます。値は発行時と購読時に別々に指定し、実際に効くのは低いほうです。

水準保証仕組み向く場面
QoS 0多くても 1 回送って忘れる。確認応答なし頻繁なテレメトリー。どのみち次の値が 1 秒後に来る場合
QoS 1少なくとも 1 回受け手が PUBACK を返す。沈黙は再送を意味する失えないが、二重に見えても構わない出来事
QoS 2ちょうど 1 回4 つのパケットのやり取りで重複を捨てる命令や課金など、繰り返しが不具合になる場面

保証が強いほど代償も増えます。QoS 2 は 1 通が 4 パケットになり、両端に状態も残ります。「念のためどこでも 2」という誘惑には抗ってください。1 万台のセンサーが毎秒 QoS 2 で発行すれば、ブローカーの負荷は桁違いに増え、それに見合う利点はありません。

QoS 1 の「少なくとも 1 回」は文字どおりです。重複は起こり得るし、正常です。同じメッセージを二度処理すると論理が壊れるなら、ペイロードにイベント ID を入れ、受け手側で繰り返しを捨ててください。QoS 2 より安上がりです。

retain、Last Will、セッション、キープアライブ

retain — 最後に判明した値

普通のメッセージは、その瞬間に購読している相手にしか届きません。retain の印が付いたメッセージは、ブローカーが覚えておき、新しく購読した相手にその瞬間に手渡します。ダッシュボードを開いても空のままで、センサーが次の値を送る気になるまで何も出ない——この古くからの悩みへの標準的な答えです。

1 つのトピックに残る retain メッセージはちょうど 1 通、最新のものだけです。消すには、同じトピックへ retain を立てた空のペイロードを発行します。

Last Will — 回線が落ちたときのための一言

接続時にクライアントは遺言をブローカーへ預けられます。トピック、ペイロード、その設定です。DISCONNECT なしに無作法に接続が切れると、ブローカーがそのメッセージを本人に代わって発行します。典型は retain の device/42/status で、接続時に online を書き、遺言として offline を預けるやり方です。問い合わせをまったくせずに、誰がいるのかを常に把握できます。

セッション:クリーンと永続

クリーンセッションは接続と同じだけ続きます。切れば購読は忘れられます。永続セッションは切断を越えて残り、ブローカーが購読を覚え、クライアントが留守の間 QoS 1 と 2 のメッセージを待ち行列に積み、戻ってきたときにまとめて届けます。1 時間に一度だけ目を覚ます機器にとって、取りこぼさない唯一の方法です。

キープアライブ — 回線が死んだと気づくために

切れた TCP 接続は、両端から見て長いあいだ健在に見えることがあります。そこでクライアントはキープアライブの間隔を宣言し、ほかに送るものがなければ ping を送ります。ブローカーは 1.5 倍の間隔だけ何も聞こえなければ、そのクライアントを失われたものとみなし、接続を閉じて遺言を発行します。

各版:3.1、3.1.1、5.0

実務で出会うのは 3 つの版で、違いは見た目だけの話ではありません。

位置づけ要点
MQTT 3.12010古いIBM の仕様。クライアント ID は 23 文字まで。いま選ぶ理由はない
MQTT 3.1.12014OASIS 標準、ISO/IEC 20922最も広く使われている版。事実上あらゆる製品が対応
MQTT 5.02019OASIS 標準大幅な作り直し。パケットプロパティ、理由コード、共有購読

これらとは別に MQTT-SN があります。TCP のない網(ZigBee、無線回線、UDP)のための兄弟分のプロトコルで、「MQTT の一版」ではなく独自の仕様です。そうした網にはゲートウェイを置き、通常の MQTT へ翻訳します。

3.1.1 と 5.0 は問題なく共存します。両方に対応するブローカーは同じポートで両者をさばき、3.1.1 のクライアントは 5.0 のクライアントが発行したメッセージを問題なく受け取ります。一斉に移行する必要はありません。ファームウェアの更新に合わせて順に移してください。

MQTT 5.0 が実際に与えてくれるもの

バージョン 5 は、現場で積み重なった不満から生まれました。とくに効いてくるのは次の点です:

  • 理由コード。3.1.1 では拒否は黙って閉じられたソケットに見え、あとは推測するしかありませんでした。5.0 ではサーバーが理由を告げます。パスワードが違う、そのトピックの権限がない、パケットが大きすぎる。
  • パケットプロパティ。メッセージがメタデータを運べます。Content TypeCorrelation Data、任意のキーと値の組。以前はそれらをペイロードやトピック名に押し込んでいました。
  • 要求と応答。Response TopicCorrelation Data により、ふつうの RPC が自作の取り決めではなく一級の型として扱えます。
  • 共有購読$share/グループ/フィルター)。同じ受け手の複数のインスタンスが流れを分け合います。これはプロトコル水準での負荷分散と冗長化です。
  • セッションとメッセージの寿命。Session ExpiryMessage Expiry により、「クリーンか否か」の二択ではなく「1 日保って、その後は忘れる」と指定できます。
  • フロー制御。Receive Maximum は未確認のまま飛んでいるメッセージの数を抑え、Maximum Packet Size は小さな機器を消化しきれないパケットから守ります。
  • トピックエイリアス。長い名前は一度だけ送り、以後は 2 バイトの番号で置き換えます。階層が深いほど効きます。
  • 購読識別子、No Local、Retain As Published、Retain Handling。古くからの落とし穴を消す細かな改良です。自分のメッセージの反響を聞いてしまう、再接続のたびに retain がなだれ込む、どの購読で届いたのか分からない、といった問題が解けます。
  • 遅延する遺言。Will Delay Interval があれば、一瞬の途切れで警報が鳴りません。期限内に戻らなかったときだけ遺言が公開されます。

実務上の結論は、新しい案件は 5.0 で始めるのがよい、ということです。共有購読と分かりやすいエラーコードは何週間分ものデバッグを節約し、古い機器との互換性も失われません。

MQTT と HTTP、そのほかの選択肢

「REST があるのに、なぜ MQTT が要るのか」はもっともな問いです。違いは流行ではなく、やり取りの向きと費用にあります。

MQTTHTTP / REST
方式発行と購読、多対多要求と応答、1 対 1
口火を切るのはどちらからでも。サーバーはいつでも送れるクライアントのみ。サーバーは尋ねられるまで黙る
接続1 本を長く保つふつうは要求ごとに新しく張る
上乗せ2 バイトから数百バイトのヘッダー
変化を知る方法向こうから届く一定間隔で問い合わせる
切断時のふるまい待ち行列、再送、retain、遺言要求がただ失敗する
得意分野テレメトリー、命令、出来事文書、ファイル、連携、Web

定期的な問い合わせを考えると差が分かります。HTTP で 1 秒以内に出来事を知るには、1000 台の機器が毎秒 1000 回尋ねねばならず、その答えのほとんどは「新しいものはありません」です。MQTT なら出来事は起きた瞬間に向こうから届き、その間は通信量を消費しません。

CoAP、AMQP、WebSocket はどうか

  • CoAP は非常に小さなノード向けの UDP 上の REST です。MQTT より軽い一方、手間をかけなければ待ち行列も確実な配送も得られません。
  • AMQP はより重く、より豊かです。手の込んだ経路制御、トランザクション、業務用の待ち行列。サーバー間では理にかなっていますが、センサーには過剰です。
  • WebSocket は代替ではなく運び手です。ブラウザーの中で動かすために、MQTT 自身が WebSocket の上を通ります。
  • Sparkplug B は競合ではなく MQTT の上の層です。産業システムでのトピックの名づけ方とペイロードの符号化を定め、異なるベンダーの SCADA が同じデータを理解できるようにします。
MQTT と HTTP は互いを置き換えるものではありません。健全なシステムはたいてい両方を使います。測定値と命令の流れには MQTT を、報告書や書き出し、外部サービスとの連携には HTTP を。

トランスポート、ポート、ペイロード

MQTT は TCP の上を通り、求めるのは確実で順序どおりの配送だけです。慣例のポートは次のとおりです:

ポート用途
1883TCP 上の MQTT、暗号化なし
8883TLS 上の MQTT — 保護された接続の標準ポート
80 / 443WebSocket 上の MQTT。ブラウザーから、あるいは厳しい企業ファイアウォールを越える唯一の道になることが多い

プロトコルにとってペイロードは単なるバイトの並びです。MQTT は中身を知らず、何も強制しません。JSON、CBOR、protobuf、数値ひとつ、画像でも構いません。形式上の上限は 256 MB ですが、実務では数百キロバイトを超えるものは HTTP に任せ、MQTT ではその場所を指す情報だけを送るのが筋です。

実際には JSON が主流です。人が読め、どの言語でも解析でき、十分に小さいからです。細い回線ではバイナリ形式が値打ちを出します。まさにそこで MQTT 5.0 の Content Type が、中身が何かを正直に告げて助けになります。

安全性

MQTT 自体は何も暗号化しません。ポート 1883 ではユーザー名もパスワードも平文で流れます。安全性は独立した 3 つの層から生まれ、そのどれも省けません。

経路を暗号化する

ポート 8883 の TLS です。TLS を扱うには非力すぎる機器については、隔離した網に置き、ゲートウェイ以外からは何も外へ出さないのが唯一まともな方法です。

認証

定番は CONNECT パケットに入れるユーザー名とパスワードです。より厳しいのはクライアント証明書で、機器が自分の証明書を示し、ブローカーが署名を検証します。より柔軟なのは JWT で、機器が署名済みで期限のあるトークンを持参し、失効させるのにブローカー側の変更は要りません。良いブローカーは外部データベース、CSV ファイル、HTTP サービスからアカウントを読むこともでき、機器一覧を二重に持たずに済みます。

トピックの権限

認証は「あなたは誰か」に答え、認可は「何をしてよいか」に答えます。アクセス制御の一覧は、どのトピックを読めて、どのトピックへ書けるかを定めます。正しい設定は明示的に許したもの以外はすべて拒否です。

実際の導入で最も多い誤りは、センサーに # の読み書きを許してしまうことです。ファームウェアの中身を 1 つ抜き出されれば、攻撃者はシステム全体の通信を見て、どの機器にも命令できます。各機器は自分の枝に閉じ込めてください。device/{id}/# だけで十分です。

そこに発行の頻度制限(暴走した 1 台がブローカーを埋め尽くさないように)、パケットの最大長、そして当たり前の網の衛生が加わります。ブローカーのダッシュボードをインターネットにさらす理由はありません。

MQTT が実際に使われている場所

スマートホームとビル管理

台数でいえば最大の分野です。Home Assistant、Zigbee2MQTT、ESPHome、openHAB はいずれも MQTT ブローカーを介して話し、そのブローカーが異なるメーカーの機器をつなぐ接着剤にもなります。3 社のコンセント、漏水センサー、暖房コントローラーが見事に協調するのは、それぞれが自分のトピックへ書くだけだからです。

産業と SCADA

機械の計測値、ラインの状態、稼働時間の集計。典型は、設備から Modbus や OPC UA を読み取って MQTT で再発行するゲートウェイを置く構成です。そのあと SCADA、履歴データベース、予知保全のシステムが互いに邪魔せず同時に受け取れます。Sparkplug B と MQTT 5.0 の共有購読が値打ちを出すのはここです。

計量と公共インフラ

水道、ガス、電気、熱の各メーター。1 時間に一度目を覚まし、値を送り、また眠る電池駆動の機器です。ここでは永続セッションと retain が働きの中心で、あるメーターが夕方まで顔を出さなくても、サーバーは常に最新の値を見られます。

輸送とテレマティクス

位置、燃料の消費、冷凍庫の状態、運転のふるまい。回線はトンネルや郊外で消える携帯網です。待ち行列と再接続後の再送が、ちぎれがちな接続を途切れないデータの流れに変えます。

エネルギー、農業、医療

太陽光発電所や変電所、灌漑設備や気象観測所、患者モニターやワクチン用冷蔵庫。共通するのは、端点が多く、回線が弱く、失ってはならない出来事があり、故障を直ちに知る必要があることです。

スマートシティと物流

街路照明、駐車場、満杯の度合いを知らせるごみ容器、貨物の追跡、低温物流の温度。数万台の機器が短いメッセージをまばらに送る——まさに MQTT が想定した負荷の姿です。

トピック設計:早めに決めておきたいこと

トピックの構成はシステムの API そのものです。あとから変えるのは痛みを伴います。ファームウェアとサーバーを足並みをそろえて更新しなければならないからです。時間を節約する目安をいくつか挙げます。

  • 大きいものから細かいものへ。plant/hall3/line2/machine7/temperature なら、どの階層でも購読できます。逆順にするとワイルドカードが役に立ちません。
  • 機器の ID には独立した階層を与える。これがあるからこそ、ACL 1 本で機器を自分の枝に閉じ込められます。
  • 先頭に斜線を置かない。/office/temp は空の第 1 階層を作ります。規格上は正しくても、長く混乱の種になります。
  • ラテン文字、数字、ハイフン、下線だけを使う。空白や名前の中の +#$ は、誰も予期しない不具合を招きます。
  • 変化する値をトピックに埋め込まない。sensor/42/temp/21.5 は誤りです。値はペイロードに入れましょう。さもないとトピックの木が際限なく増え、retain が役に立たなくなります。
  • 状態と命令を分ける。たとえば機器が知らせる内容は device/42/state、機器へ指示する内容は device/42/cmd に。さもないと自分の命令の反響でいずれ論理が回り出します。
  • retain は状態に、テレメトリーには使わない。retain は「最後に判明した状態」に向いており、測定値の流れには意味がありません。
版の管理も早めに決めてください。トピックの先頭に v1 の階層を置くのは今は無料も同然で、2 年後に古い機器群を壊さずに新しいペイロード形式を展開できます。

ブローカーの選び方

ブローカーは数多くありますが、選択はたいてい少数の問いに落ち着きます。

  • MQTT 5.0 に完全対応しているか。部分的な対応はよくあることで、しかもたいてい最悪の場面でそれを知ります。
  • 何が起きているか見えるか。誰が接続していて、どのトピックが生きていて、いま何が飛んでいるかを見られると、デバッグの時間が何時間も減ります。ダッシュボードのないブローカーは、あらゆる問題をログの発掘作業に変えます。
  • 機器はどうやって登録するか。数千台ともなれば手作業は論外で、API か外部データベースのアカウントが要ります。
  • 再起動しても残るか。retain メッセージ、永続セッション、待ち行列はディスクに届いていなければならず、そうでなければ計画的な再起動でもデータを失います。
  • どんな制限が使えるか。暴走した 1 台にシステムを落とさせないために、頻度と量の制限が効いてきます。
  • 費用はいくらで、どこで動くか。クラウドのサービスはメッセージ課金が始まるまでは快適です。自前のサーバーは運用の手間がかかりますが、データは手元に残ります。

スマートホームから端点数千の工場まで、小中規模の導入なら、ほどほどのサーバー 1 台にブローカー 1 つで足りるのが普通です。クラスタリングは設計中に思うほど必要になりません。それより、独立した 2 つのブローカーをブリッジでつなぎ、重要なトピックだけ転送するほうが得なことが多いのです。

ELX-MQTT Broker はこの一覧を満たします。両方のプロトコル版に完全対応し、動くグラフとメッセージの流れを備えた Web ダッシュボード、トピック ACL、機器登録用の REST API、SQLite への状態保存、頻度制限、ブリッジを備えます。Debian と Ubuntu ならコマンド 1 つ、Windows ならインストーラーで導入でき、無料でデバイス数の制限もありません。

5 分で始める

ここまでの話を最も早く理解する方法は、ブローカーを動かして自分でメッセージを眺めることです。Debian か Ubuntu ならコマンド 3 つで済みます:

sudo wget -qO /usr/share/keyrings/elx-repo.gpg https://repo.um-d.ru/elx-repo.gpg
echo "deb [signed-by=/usr/share/keyrings/elx-repo.gpg] https://repo.um-d.ru stable main" | sudo tee /etc/apt/sources.list.d/elx-repo.list
sudo apt-get update && sudo apt-get install elxmqttbroker

ダッシュボードは http://あなたのサーバー:8567 で開きます。ユーザーを作り、好きなクライアントでやり取りを試してください。たとえば mosquitto のコンソール用ツールで:

# 片方の画面で — 機器が送るものをすべて購読する
mosquitto_sub -h localhost -u sensor-42 -P password -t 'sensor-42/#' -v

# もう片方で — 測定値を発行する
mosquitto_pub -h localhost -u sensor-42 -P password -t 'sensor-42/temp' -m '21.5'

# 同じだが、後から購読する相手のために覚えさせる
mosquitto_pub -h localhost -u sensor-42 -P password -t 'sensor-42/temp' -m '21.5' -r

あとは retain の印を試し、購読者を切断して永続セッションに何が溜まるかを見て、遺言を設定してケーブルを抜いてみてください。この 30 分は、この記事を含むどんな文章よりも多くを教えてくれます。

手短な回答

MQTT をやさしく言うと何ですか?

機器どうしが仲介役を通じて短いメッセージをやり取りする方法です。機器は名前の付いた「トピック」へメッセージを送り、そのトピックを購読しているプログラムがすぐに受け取ります。送り手と受け手は互いを知らないため、どちらも独立して差し替えたり増やしたりできます。

なぜ MQTT ブローカーが必要なのですか?

ブローカーは、すべての機器との接続を保ち、権限を確かめ、発行されたメッセージを購読と照合して写しを配るサーバーです。これなしに MQTT は成り立ちません。発行と購読はブローカーの中で出会います。

MQTT 5.0 は 3.1.1 とどう違いますか?

主な違いは、黙って閉じられる接続ではなく分かりやすい理由コードが返ること、メタデータを運ぶパケットプロパティ、一級の型としての要求と応答、受け手のあいだで負荷を分ける共有購読、制御できるセッションとメッセージの寿命、フロー制御、そして帯域を節約するトピックエイリアスです。

MQTT 5.0 へ移るべきですか?

新しい案件なら移るべきです。得られるものは実際にあり、互換性も保たれます。既存の 3.1.1 のシステムを急いで移行する必要はありません。両方の版が同じブローカーで同時に動くので、ファームウェアの更新に合わせて少しずつ切り替えられます。

どの QoS を使えばよいですか?

測定値を 1 つ落としても構わない頻繁なテレメトリーには QoS 0。失えない出来事には QoS 1(受け手が重複を捨てられることが前提)。二度処理してはいけない命令や課金にだけ QoS 2。「念のため」でどこでも QoS 2 にするのは、ブローカーを過負荷にする最短の道です。

MQTT の retain とは何ですか?

メッセージを覚えておき、新しく購読した相手にその瞬間に手渡すよう、ブローカーへ指示する印です。1 つのトピックに残るのは最新の 1 通だけです。「センサーの次の更新を待たずに、いまの状態をすぐ見せる」ための標準的な答えで、同じ印を付けた空のペイロードを発行すれば消せます。

Last Will とは何ですか?

クライアントが接続時にブローカーへ預けるメッセージで、正常な切断なしに接続が死んだとき、ブローカーが本人に代わって発行します。ふつうは機器をオフラインとして印を付けるために使い、システムは問い合わせをせずに喪失を知ることができます。

MQTT は安全ですか?

プロトコル自体は何も暗号化しません。ポート 1883 ではパスワードが平文で流れます。安全性は、ポート 8883 の TLS、パスワード・証明書・JWT による認証、そして「明示的に許したもの以外は拒否」で働くトピック単位のアクセス一覧から生まれます。

1 台のブローカーで何台の機器を扱えますか?

ブローカーと負荷によりますが、目安としては、ごく普通のサーバー上の 1 プロセスで、典型的なテレメトリーなら数万の同時接続を余裕をもって保てます。上限を決めるのはたいてい機器の台数ではなく、メッセージの頻度と求める QoS です。

MQTT はブラウザーで動きますか?

はい、WebSocket 上の MQTT で動きます。ブラウザーは任意の TCP 接続を開けないため、プロトコルを WebSocket で包みます。おかげで Web のダッシュボードが、間にサーバーを置かずに直接トピックを購読できます。

トピックの + と # は何を意味しますか?

購読で使うワイルドカードです。+ はちょうど 1 階層を置き換え、# は残りのすべての階層を覆い、フィルターの末尾でしか使えません。ワイルドカードを含むトピックへは発行できません。購読専用です。

モノのインターネットで MQTT が HTTP より優れているのはなぜですか?

定期的な問い合わせが不要で、出来事が起きた瞬間にメッセージのほうから届くからです。上乗せは数百バイトではなく 2 バイトから、接続は 1 本を長く保ち、待ち行列・再送・retain が回線の切断をデータを失わずに乗り切らせます。報告書やファイル、連携には HTTP のほうが優れた道具のままです。