HTTP WebPushがIoTで使えない3つの理由

HTTP WebPushは、IoTで使えるものと期待されています。しかし、RFCを読み解いた結果、「使えない」と解釈しました。この記事で理由を述べたいと思います。

なお、HTTP WebPushは、後で述べますように、プロトコル作成者側としてはIoTをターゲットとして十分意識しています。しかし、HTTP WebPushをIoT向けに使おうとした論考は、日本語/英語ともに、まだほとんど見かけない状況です。そのため、本テーマに関して、主流となる論調はまだ確立されていません。そんな中で、本記事では大胆に「使えない」と断言してみました。

# 1. なぜHTTP WebPushがIoTで期待されているか

センターのアプリケーションサーバから、IoTデバイスにメッセージを送る上で、既存の手段は一長一短があります（それぞれの手段について、この記事では説明は省略します）。

|既存の手段|即時性|センター負荷|通信コスト|到達性|汎用性|
|:-----|:-----:|:-----:|:-----:|:----:|:----:|
|HTTP polling|△|○|○|◎|◎|
|APNS/GCM|◎|○|○|△|△|
|mqtt|◎|△|◎|◎|◎|
|SMS|○|◎|×|○|○|

なお、HTTP/2 ServerPushというものがありますが、これはブラウザの先読みキャッシュをサーバからPUSHするものであり、任意のメッセージをPUSHするものではありませんでした。

これに対して、HTTP WebPushは、HTTP/2 ServerPushをベースにしつつ、APNS/GCMを標準化したものとして位置付けられています。そのため、APNS/GCMの特長を維持しながら、到達性（HTTPS利用）と汎用性（標準方式で特定クライアントに依存しない）を兼ね備えた、万能な解決策になる可能性があると、期待されています。

# 2. HTTP WebPush (RFC8030)の概要

2016年12月に、RFC8030 draft standardが公開されています。
https://tools.ietf.org/html/rfc8030
この内容をもとに、概要を紹介します。

## 2.1. ターゲットとしてIoTを意識

Introductionを見ると、組み込みの低消費電力デバイスで無線通信の常時接続が難しいことなど、IoTをターゲットとしてかなり意識した内容になっています。

## 2.2. プロトコルの概要

クライアントであるUAと、アプリケーションサーバとの間のPUSHメッセージを、Push Serviceというブローカーが仲介します。

![スクリーンショット 2017-05-31 0.07.46.png](https://qiita-image-store.s3.amazonaws.com/0/156600/9f893a7d-ce9f-8827-fdff-8baf214408bb.png)

プロトコルのポイントは以下です。

+ HTTPS(443/TCP)のサポートがMUST。HTTPS？(1001/TCP)のサポートがMAY
+ ブローカーであるPush Service上のリソースをCreateしていくことでPub-Subを実現
  + UAがPUSHリソースをCreateすることでSubscribe
  + 以降、UAはPUSHリソースをメッセージ監視する（★）
  + UAは適当な手段でアプリケーションサーバにPUSHリソースを伝える
  + アプリケーションは、PUSHリソースに対して、PUSH messageリソースをCreateすることで、メッセージをPublishする
+ Subscriptionの重畳（同報）、メッセージのTTL、緊急度、上書き、返信などが規定されている
+ Push Serviceにおける盗聴、改ざん、なりすましを防止するために、エンドツーエンドでメッセージを暗号化、署名、相手先の認証をすることがMUSTとなっている
+ リソース操作の認可については、本プロトコルでは規定しない

## 2.3. メッセージ監視のしくみ

前項の★の部分のメッセージ監視は、HTTP/2 ServerPushのしくみで行われます。

+ UAがPUSHリソースをGET
+ Push Serviceはすぐにレスポンスを返さない。UAからのセッションは貼りっぱなし。
+ アプリケーションサーバからメッセージがPublishされたら、Push Serviceは、ServerPushで規定されているPUSH_PROMISEメッセージにより、PUSHするストリームを予約する
+ Push Serviceは、予約したストリームに実際のメッセージをPUSHする

# 3. HTTP WebPushがIoTで使えない3つの理由

これまでの情報をもとに、HTTP WebPushがIoTで使えない理由を、3つ説明します。

## 3.1. コネクション維持が前提となりmqttで十分

HTTP/2 ServerPushの前提として、コネクションを維持する必要があります。ブラウザの先読みキャッシュをPUSHする、という従来の目的であれば、コネクション維持は短時間で十分ですが、IoTでのPUSHを想定すると、長時間の維持が必要です。

結局、mqttでコネクション維持するのと、本質的には同じになってしまいます。そうであればIoT向けの効率化機能が充実しているmqttを使うべきであると思います。

mqttのポート番号に起因する到達性（Proxy超えなど）が気になる場合は、over WebSocketを使えば十分です。

## 3.2. APNS/GCMのような特別扱いは期待できない

項1の表で、APNS/GCMがmqttに対して唯一勝る点として、センター負荷をあげました。これは、APNS/GCMのコネクション維持に関するポーリング間隔がかなり長くとれ、センター負荷に優しいからです。なぜポーリング間隔を長くとれるかというと、通信キャリアがApple様/Google様を優遇して、APNS/GCMのコネクションを長時間切らない特別対応をしているからなのです。

しかし、WebPushとして標準化され、汎用の443/TCPで誰でもブローカーを立てられるようになれば、それを通信キャリアは特別優遇しません。よって、センター負荷における優位点は、雲散霧消してしまいます。

## 3.3. 最大の特長であるブローカーの独立性はIoTでは使い所が無いとともに害悪である

そもそも、HTTP/2 ServerPush単独に対して、WebPushは何を追加しているのでしょうか。それは、クライアントであるUAが、任意の不特定多数のアプリケーションサーバと接続する際に、PUSHのしくみであるブローカーを、アプリケーションサーバーとは独立して提供でき、共通化できるということです。

一方、IoTの通常のユースケースは、PCやスマートフォンと異なり、任意の不特定多数のアプリケーションサーバと接続するというものではありません。そのため、特定の少数のサーバとの間でHTTP/2 ServerPushを使えば十分で、WebPushを使う必要はありません。

現状、ブラウザで実現されているServerPushの機能は、キャッシュ先読みであり、メッセージPUSHはできませんが、項2.3で見たように、メッセージPUSHのしくみとしてはServerPushを何も変えずに使っていますので、ブラウザの実装次第で、（特定サーバとの）メッセージPUSHは実現可能です。よって、IoTでわざわざWebPushを使う必要は無いのです。

逆に、ブローカーが独立であるがために、エンドツーエンドでのセキュリティ対策が必須となり、非力なIoTデバイスにとっては、利用し難い仕様になってしまっています。ブローカーの独立性はIoTにとっては害悪なのです。