はじめに
Web系の技術情報でたまに見かけてた「push技術」という言葉がずっと気になっていて、ふとしたきっかけで調べたので覚書。
単語は知らないけど、実は仕組みは知ってたってよくある話ですよね。
その前に: よくある2者間のデータ共有方法
どの分野の話でも、更新されていくデータの共有方法については、ざっくりと2種類方法があります。
ポーリング型は情報取得側で何とか出来るので考えることが少なくていい半面、更新のリアルタイム性が低くなります。
そのため、リアルタイム性の高いイベント型のデータ共有方法があるのは
図は以下記事のものを参照させていただきました。実際のクライアントサイド実装方法が記載してある良記事でしたので、Webクライアントサイドの参考にいいと思います。
リアルタイムなwebアプリを実現する方法(ポーリング、Comet、Server Sent Events、WebSocket)
ハードに近い層の方が使う言葉だと、イベント型は割り込みと呼んだりもしますね。
HTTPでのイベント型実現方法
HTTPだとPush技術あるいはserver pushという呼び名で扱われています。
HTTP 1/1, HTTP/2ともに同じTCPセッション上で都度response dataを投げる形になります。上で書いたイベント型の図のままですね。
HTTP 1/1はTransfer-Encoding: chunked
HTTP 1/1の場合はTransfer-Encoding: chunkedを利用したHTTP responseを使う方法があります。通常はresponseヘッダーにContent-Lengthが付くんですが、その代わりにTransfer-Encoding: chunkedを指定します。
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked <-Content-Lengthを指定せず、代わりにこれを指定
Transfer-Encoding: chunkedを付けた場合にどうやってデータ長を知るかというと、先頭に長さ\r\nを付けるだけです
(大体サーバーHW/OSSやブラウザで勝手に対処してくれるので、Transfer-Encoding: chunkedだけつけておけばOKってケースが多いと思います)
7\r\n
Mozilla\r\n
最後は0\r\n\r\nを付けて終わり。
7\r\n
Network\r\n
0\r\n
\r\n
こちらの方法を使い、最初のresponseでヘッダーだけ返して、後は変更がある度にchunkedで通知するといった表現が可能になります。
他にもon HTTPの映像配信のように定期的にデータを送信し続ける仕組みや、大きい過ぎてresponse作成に時間のかかるデータを分割したりなんてのにも使えます。
似たような技術でmultipart/form-dataを使った方法も見たことあります。こちらはHTTPボディの中に複数のHTTP responseヘッダー+ボディを詰めた感じです。
HTTP/2でのデータ共有方法
HTTP 1/1では1 HTTP requestに対して1 HTTP responseが基本だったため、1 responseを分割するchunked形式が活躍していました。
それに対してHTTP/2ではより高速・効率的な通信を行う為の方法が提供されています。
(実践比較してないので仕様上の話しかできなくてすいません。。)
HTTP/2ではstreamを使って複数データ送受信が可能
一方HTTP/2では接続が確立した通信の上でstreamというものを作って、stream単位でrequest/responseを扱います。なのでchunkedでやりたかったことがstream上で普通に扱えるので便利ですね。chunkedの代わりにフレームという単位でデータを扱っている感じですね。
HTTP/2ストリーム、メッセージ、フレームより図を抜粋です。
HTTP/2 サーバープッシュ
HTTP/2が提供する新機能の中にサーバープッシュという名称の機能があります。
これはざっくりいうと「扱うことが分かっているリソースをサーバーから送信してあげる」って感じなので、イベントとは少し違いますね。ただサーバー契機での送信になるので合わせて記載しておきます。
参考
実装の参考:リアルタイムなwebアプリを実現する方法(ポーリング、Comet、Server Sent Events、WebSocket)
MDN Web Doc/Transfer-Encoding
HTTP/2の概要