wakasann
1/1/2015 - 2:01 PM

初めての MQTT

初めての MQTT

#############
初めての MQTT
#############

:作: @voluntas
:バージョン: 1.0.1
:URL: https://voluntas.github.io/

2015 年 1 月 12 日に行われた `「テレビ連動サーバー」勉強会 <http://connpass.com/event/10424/>`_ 向けの発表資料です。

`プレゼン資料はこちら <https://speakerdeck.com/voluntas/chu-metefalse-mqtt>`_


概要
====

本日は皆さんが MQTT というほとんど聞いたことが無いであろう、話をさせて頂きます。

基本的な話が中心になります。もし話を聞いて MQTT に興味を持った人は実装の過程と苦労の二つを書いた話を公開しているのでこちらをどうぞ。

- `時雨堂 MQTT ブローカー開発ログ <https://gist.github.com/voluntas/558fea1445253e6dc6c2>`_
- `時雨堂 MQTT ブローカー (Akane) <https://gist.github.com/voluntas/14a3421585bb08379314>`_

また、 `MQTTについてのまとめ — そこはかとなく書くよん。 <http://tdoc.info/blog/2014/01/27/mqtt.html>`_ というとても良くまとまっている記事もありますので、そちらをご覧ください。

自己紹介
========

`時雨堂 <https://shiguredo.jp>`_ という会社から来ました。

ちなみにテレビは持っていません、ごめんなさい。

Erlang/OTP と Lua を書いてます。興味は自動負荷試験と自動障害試験。

普段は落ちてはいけないシステムの設計と開発をメインでご飯を食べています。

最近ですと、去年上場した gumi 様の認証や課金基板、さらにはゲーム用の AI システム基盤などを開発や NTT コミニュケーションズ様の WebRTC 用のシグナリングサーバー (仲介システム) SkyWay を作ったりしています。

MQTT とは
=========

MQTT は簡単に言うと土管です。

クライアントとクライアントを繋ぐための土管システムです。

これから、その土管の特徴を話させて頂きます。

MQTT ブローカー
---------------

PubSub でメッセージを配信するサーバのことを MQTT ブローカーと呼びます。

::

                                                        <- メッセージを受け取る <- クライアント
    クライアント -> メッセージを送る -> MQTT ブローカー <- メッセージを受け取る <- クライアント
                                                        <- メッセージを受け取る <- クライアント


クライアントからメッセージを受け取って、クライアントにメッセージを配るサーバと考えて頂いて問題ありません。


メッセージ
----------

そもそもキモとなるのがメッセージという概念です。

メッセージとは A から B に届ける内容と考えて貰ってかまいません。

ただし、メッセージを送るのは **相手** ではなく、あくまで **宛先** です。

A さんと B さんがいて、メッセージのやりとりをします。

よくあるのは「 A さんが B さんにメッセージを送る」という例ですが、 MQTT の場合は違います。

メッセージを送る先の指定は B さんではなく B さんが提示している宛先です。

B さんが自分への宛先を XYZ としていれば、A さんは XYZ に対してメッセージを送ります。

B さんは XYZ に来たメッセージを受信するという流れです。

PubSub
------

MQTT が普通の土管と違うのが一対多、つまり1つのクライアントのメッセージを、たくさんの人に配る仕組みを持っています。これは PubSub と呼ばれる仕組みです。

このシステムを使うことで 1 度にたくさんの人に **ほぼリアルタイムで** メッセージを配信することができるようになるということです。

Publisher と Subscriber
-----------------------

PubSub とは Publisher (パブリッシャー) と Subscriber (サブスクライバー) を繋いだ言葉です。

- パブリッシャーとはメッセージを配送する人
- サブスクライバーとはメッセージを購読する人

送信と受信といっても別に良いのですがあえて分けています。

PubSub で説明したとおり 1 つのパブリッシャーから複数のサブスクライバーに送る事ができます。

パブリッシャーとサブスクライバーの共通事項がトピックです。

Topic
-----

MQTT にはトピックという仕組みがあります。

これは **メッセージの送り先を指定することができる** と同時に **メッセージを指定して受け取ることができる** 機能です。

イメージしにくいと思いますので、もうすこしかみ砕いていきます。

トピックは / (スラッシュ) 区切りで指定することができます。

トピック例::

    柔道/男子/金メダル
    柔道/女子/金メダル
    体操/男子/金メダル
    体操/男子/銀メダル
    
これはトピックの例です。MQTT ではメッセージを送るときに、これらのトピックを指定して送る事が出来ます。つまり柔道/男子/金メダルの情報を送る事ができます。

受信側はこれらのトピックを指定して、どの情報を受け取りたいかを MQTT ブローカに伝えます。

ワイルドカード
^^^^^^^^^^^^^^

MQTT のトピックは面白い仕組みがあります。それはワイルドカードと呼ばれ、 + と # という記号で表されています。

このワイルドカードは受け取る側しか使えません。送る側は使えません。


ワイルドカード例::

    +/+/金メダル
    柔道/#

+ はワイルドカードの一つで、+ は **なんでもいい** という意味です。


- **+/+/金メダル** というのは何でもいいから金メダルの情報だけを得たい場合のワイルドカードを使ったトピックです。
- **柔道/#** というのは柔道であればなんでもいいので情報を得たい場合のワイルドカードを使ったトピックです。

Retain
------

MQTT には独特な機能としてリテインという機能があります。これは **トピック事に最新のメッセージを MQTT ブローカーが保持しておいてくれる** という機能です。

もう少し具体的に説明していきます。

MQTT ではメッセージが配信されているときに接続しているクライアントにメッセージを配信するとういのが基本的な動作です。

つまり配信時に **電波が切れていた** や **携帯の電源を切っていた** という状況の場合はメッセージが配信されません。

しかしリテインを使う事で、常に最新のメッセージを保持することが出来るのです。

例
^^

たとえば、クイズが 10 問あるとします。ただ、クイズには配信時間があります。その配信時間に繋いでいない場合は、接続時に今の状態を確認し、今何問目なのかどうかを確認してクイズに参加する必要があります。

しかし、リテインを使う事で最新のメッセージが保存されるので、接続した瞬間に今何問目かがわかるようになっています。

::

    トピック: 日本/東京都, メッセージ: 4 問目
    トピック: 日本/神奈川県, メッセージ: 5 問目

リテインはトピック事に保持されます。リテインが有効な場合は接続したタイミングですぐメッセージが流れてきます。

つまりデータベースに負担をかけることなく、最新のクイズが確認出来るようになります。

Will
----

will は遺言と呼ばれる機能です。何かしら想定外の切断が合った場合、事前に設定しておいたトピックに対して、遺言を送ります。

つまり、クライアントに **想定外の切断** が起きた事を知ることができます。

この機能はクライアントが自分から切断した場合は発生しません。そのため電波の届かないところにいった、パソコンが落ちたといった、異常終了を検知できます。

異常終了をトリガーとして何かしらの処理を実行することが出来るようになります。

例
^^

サーバの監視に使うってみることを想定してみることにします。

サーバの情報を常に送り続けていますが、ネットワークの切断やサーバの異常停止などを will を使う事で簡単に検知できます。

もし正式な計画シャットダウンの場合は正式な手順を追ってクライアントを終了すれば will によるメッセージは発生しません。

will を使う事でサーバの障害を **リアルタイム** に気付くことが出来るようになります。

QoS
---

QoS とは Quality of Service の略です。

簡単に行ってしまえば土管を使って相手に届けるときの確実性を定義出来ます。

QoS には 3 段階あります。

- QoS レベル 0 は **最大 1 回** 届きます
- QoS レベル 1 は **1 回以上** 届きます
- QoS レベル 2 は **正確に 1 回** 届きます

クライアント側は特に意識すること無くメッセージを送る時に QoS を定義するだけでかまいません。

あとは MQTT ブローカーが良きに計らってくれます。

基本的には QoS 0 でかまいません、確実に届けない課金情報などに 1 以上を使う感じでかまいません。

ちなみに QoS が上がれば上がるほど MQTT ブローカーの性能に影響します。

事例
====

現実世界で有名で良く例に出てくるのは Facebook Messenger です。

Facebook Messenger は MQTT ベースで作られています。数億人の基盤を支えている技術といっても過言では無いでしょう。

最初にお話ししたように複数人数にメッセージを同時に送ったり、ぎゃくに PUSH 通知でリアルタイムにメッセージを受信したりといった土管を提供するのが MQTT ですので、相性はよさそうです。

MQTT over WebSocket
-------------------

MQTT はプロトコル、つまり通信規格の一つで基本的には TCP/IP 上での動作を前提としています。

ただし、WebSocket 上でも動作させることが出来ます。つまりブラウザ上で MQTT を使える用になります。


もともはセンサーや、何かしらのリアルタイムな情報を WebSocket を使ってブラウザに実際にグラフを作ったりするのが目的で使われ始めた機能のようです。

実際、管理画面側でのブラウザで見れるグラフを作成するのにとても向いている用です。


まとめ
======

今回紹介した機能以外にも、オフライン時のメッセージを **全て** 保存してくれるセッション、仕様外になりますが、ユーザ認証ベースによる誰がどのトピックにメッセージを送ったり受け取ったりするかを制限するパーミッション機能などもあります。

MQTT はメッセージを配信するための土管です。様々な用途に使える基盤に近いモノです。特にリアルタイムで多数にメッセージを送ったりする仕組みにとても使えると思います。

テレビでは最近ネットワークとの連動が増えていると聞きました。もしかするとこの技術が活躍出来る場所があるかもしれません。

何かあればお声がけください。

contact at shiguredo.jp