QoSとは?MQTTにおける通信の種類!
2018/01/25
IT/IoTこんにちは、さきです!
先日、MQTTについての記事を書きました。
MQTTってどんなもの?
MQTTとは?あとで自分で読み返すためのメモも兼ねて、MQTTについてまとめてみました!自分がMQTTを勉強する上でわかりにくかったところを詳しく書いています。Publisher、Subscriber、Broker、Topicといった、MQTTを考える上で重要になる用語についても詳しく説明しています。
ですがもうひとつ、上の記事に書いていない、大事なことがありました!それは、「QoS」と呼ばれるものです。
MQTTでPublish、もしくはSubscribeする時、Topicの他にQoSも指定する必要があります。
QoSについて、なるべくわかりやすく、を意識しながらまとめてみました!
QoSとは
QoSとは、Quality of Service(サービスの品質)の略です!
郵便屋さんを例に考えてみます。誰かに手紙を送りたい時、一番安いのは多分、定形郵便です。ですが、ゆうパック等を使っても届きます。
定形郵便とゆうパックの違いは色々あります。手紙を送るとしたら、違いは「郵便の追跡」や、「受け取り通知」、「郵送事故時の保障」等ですね。そういった点で、ゆうパックは定形郵便よりも「品質が高い」と考えることができます。
では、どんな時でもゆうパックの方が優れているのかというと、そういうわけではありません。クレジットカードを定形郵便で送るのはかなり不安ですが、授業ノートのコピーを送るくらいなら定形郵便で十分ですし、ゆうパックを使うにはちょっと高いなー…と感じてしまいます。
品質が高い=いい物 とは必ずしも限らなくて、環境にマッチしているかどうかが重要になってくるようです。
QoSという言葉はMQTT以外でも使われていて、Wikipediaによると「制御工学やシステム工学の分野で広く使われる用語」だそうです!
MQTTのQoSって具体的にどんなこと?
QoSという言葉が広く使われていることはわかりましたが、MQTTでは具体的に何の品質のことを言っているのでしょうか?
MQTTのQoSは、「通信の品質」のことを指しています。もうちょっと具体的に書いてみます!
まずは図を見て下さい!
MQTTでは、赤丸で囲った部分の通信品質のことを「QoS」と言います。そして、QoSは「PublisherからSubscriberまでの全部」を言っているのではなく、赤丸で囲った細かい区間それぞれのことを言っています。図の場合だと計6個の赤丸があるので、QoSも6個それぞれに設定されています!
QoSの種類
では、MQTTのQoSが何のことを言っているのかわかったところで、本題に入っていきます。MQTTのQoSレベルは、0、1、2の、計3段階に分かれています。
「送信側」と「受信側」のやり取りを書きたいんですが、次の図のようにちょっとややこしいことになります。
Brokerが受信側になったり送信側になったりしますが、QoSを考える上では、どの区間も通信内容は同じですので「Publisherが~」とか考えずに、単純に「送信側」と「受信側」で考えて下さい。
QoS0
まずはQoS0です!最もシンプルで、最も軽量です。
メッセージを最大で1回だけ届けます。「最大で」と書いたように、通信エラー等が発生すると、メッセージが届かないこともあります。
QoS0では、「メッセージが無事に届いたかどうか」を確認しないので、きちんとメッセージが届いたかどうか送信側が知ることはできません!届くにしろ届かないにしろ、とりあえず1回だけ送信しておく、という感じです。
QoS1
次に、QoS1です!QoS1は、最低でも1回はメッセージを届けます。「最低でも」と書いたように、通信エラー等が起こると何回か重複して届いてしまうことがあります。
QoS1では、「メッセージが届いたかどうか」を確認します!確認用に、折り返し受信側から送られてくる信号を「PUBACK」と言います。
PUBACKを受信できるまで、送信側は何度もメッセージを再送します。PUBACKを受信できた時点で、再送するのをやめます。これなら、確実にメッセージは届きますね!
ところが、送信側がPUBACKを通信エラー等で受け取り損ねると、メッセージが無事に届いたにも関わらず、まだ再送を続ける、ということが起こります。
もし受信側に2通のメッセージが届いたとして、それらが「元々2通だったのか」それとも「重複して2通になったのか」を、QoS1では判別できません。なので受信側では、重複は起こらないものとして処理されます。もし重複でメッセージが2通に増えてしまったら、「メッセージが2通来たよ!」という処理になるんですね。
これが、QoS1でメッセージの重複が起こる理由です!
QoS2
QoS2は、正確に1回だけメッセージを届けます。届かないことも、届き過ぎることもありません!品質が高い反面、通信の回数が増えて、MQTTで一番遅い通信になります。
QoS2でもQoS1と同じく、「メッセージが届いたかどうか」を確認します!この時折り返しで送られてくる信号は、QoS1では「PUBACK」という名前でしたが、QoS2では「PUBREC」という名前になっています。
QoS2は、QoS1の「重複メッセージ」が起こらないような工夫を追加しています。メッセージ、PUBRECの他に、あと2つの信号をやり取りしているんです!文章で書くとわかりにくくなってしまうので、まずは流れと、図を見て下さい!
- 「送信側」→メッセージ→「受信側」
- 「送信側」←PUBREC←「受信側」
- 「送信側」→PUBREL→「受信側」
- 「送信側」←PUBCOMP←「受信側」
「PUBREL」と「PUBCOMP」が追加されていますね。
QoS1では、「メッセージが届きましたよー!」という折り返し連絡を受け取れなかったために、重複が起こっていました。QoS2でも折り返し連絡を受け取れない可能性はありますが、信号4つで1セットになっているので、もし2つのメッセージを受信したとしても「元々2つだったのか」、「重複して増えたのか」を見分けることができます。
重複が起こったかどうかを見分けることができるので、メッセージを正しく処理することができます!
QoSレベルはどうやって決まる?
QoSレベルが3つあり、それぞれの特徴もわかりました。では、QoSレベルはどのようにして決まるのでしょうか。
まず大前提として、Brokerが対応しているQoSレベルしか使用できません。対応していないQoSレベルを使用した場合、QoSのレベルが下がるのか、それとも通信そのものが行われないのかはちょっとわかりませんでした、すいません。もしわかったらその時に追記します。
以下の項目は、「BrokerがすべてのQoSに対応している」前提で書きます。
PublisherとSubscriberがQoSを指定する
Publisher側でも、Subscriber側でも、必ずQoSを指定する必要があります!BrokerがQoSを指定することはありません。QoSは、Publisher、Subscriberの指定した値によって決まります!
例えば、Publisherが「QoS2」を指定して、Subscriber①は「QoS0」、Subscriber②は「QoS1」を指定する、なんてこともあるわけです。この例だと次の図のような結果になります。
PublisherはQoS2を指定しましたが、Subscriber達はそれぞれ好きなQoSで通信を行なっています。このように、経路の途中でQoSレベルが下がることを「ダウングレード」と言います。もちろん、ダウングレードせずにメッセージを受け取ることもできますよ!この例だと、QoS2でSubscribeする、ということですね。
Publisherの指定したQoSに影響を受ける
では、常に好きなQoSで通信を行なえるかと言うと、実はそうではありません。
先ほどの例ではPublisherがQoS2、つまり最高レベルを指定していたので、Subscriberは好きなQoSレベルでメッセージを受け取ることができました。では、次のような例ではどうなるのでしょうか。図も一緒に見てみます。
例:Publisherが「QoS1」を指定。Subscriber①は「QoS0」、Subscriber②は「QoS2」を指定。
Subscriber②は「QoS2」を指定したはずでしたが、「QoS1」の通信になってしまいました!もうひとつ例を書きます。
例:Publisherが「QoS0」を指定。Subscriber①は「QoS1」、Subscriber②は「QoS2」を指定。
今度は、全てのQoSが0になってしまいました!
このように、Publisherが指定したQoSより上のレベルで通信を行なうことはできません。SubscriberがPublisherより高いQoSを指定しても、Publisherの指定したQoSレベルまで下がってしまいます。Publisher側の設定が、全体のQoSに影響を与えるんですね!
どんな場面でどのQoSがマッチするのか
QoSの仕組みもわかったところで、どんな場面にどのQoSを使うのがよいのか考えてみます。
極端な話、全部QoS2にすれば悩む必要はないですが、Brokerへの接続台数が多くなってくると、負荷が大きくなります。なので、低いQoSで運用できるのであればそうした方がいい場合もあります。全部QoS0ならBroker1台でOKだけど、QoS2だと2台必要になる、とかそんなこともあるかもしれません。
システムを運用する環境と照らし合わせて、どうするか考えるのが良さそうですね!
参考程度にいくつか、私個人のイメージを書いてみます!
QoSの決め方にルールは無いので、実際にMQTTを使用する時は皆さんが自由に決めて下さいね!
庭のトマトの状態を取得する
趣味で庭にちょこちょこっとトマトを植えてあったとします!トマト周辺の温度や湿度、光量など、取得したいデータはいくつかありますね。
データを10分に1度、MQTT経由でPCに送って、グラフ化していたとします。この時のQoSレベルはいくつにしたらよさそうでしょうか。
私なら、10分に1度データを取れて、取得したデータもグラフにするだけなので、「もし取得に失敗してデータ抜けがあっても、別に大した問題にはならない」と考えて、QoS0を指定すると思います!
子供や高齢者のみまもりグッズ
「防犯ブザー」とかのIoTバージョンみたいなのをイメージして下さい。高齢者だと、具合が悪くなったら自動で家族や、最寄りの病院にお知らせしてくれる、とか。
これは「メッセージ届きませんでした」だとマズイですよね。
重複していようが、確実にメッセージを届けることができればOKなので、この場合はQoS1になるのかな?と思います。
自動で戸締りする玄関
私が何かのデバイス、例えばLoRaWANデバイス等を持っているとします。これに反応して自動で戸締りをしてくれる玄関があったとします。ICカードでタッチすると鍵の開け閉めができる、でもいいですね。これの操作にMQTTを用いる、という設定で考えてみます。
この場合、簡単に作るのであれば、恐らく「メッセージ1回」ごとに「鍵が空く」→「鍵が閉まる」を交互に繰り返すような形になるのではないでしょうか?
交互に動作を切り替えていく場合、メッセージが届かないと鍵の操作ができませんし、重複すると複数回の動作が入って「今、鍵開いてるの?閉まってるの?どっち?」な状態になります。なので、この場合はQoS2が適切かな、と思います!
まとめ
MQTTのQoSについてまとめました!
個人的には、PUBRECとかPUBRELとか、用語を一生懸命覚えようとすると、逆になかなか覚えられませんでした。用語を最初に覚えるのをやめて、イラストにして動きを覚えて、用語は後から覚えるように工夫してみました(なんだかテスト勉強みたいですね!)。
IoTがんばるぞー!
さき