lxyuma BLOG

開発関係のメモ

Server-Sent Eventsまとめ。ハイパフォーマンスブラウザネットワーキング16章

まだ、社内でO'Reillyのハイパフォーマンスブラウザネットワーキングの読書会をやっていて、

自分が、16章のserver sent eventsやるので、その下書き。(前の資料もいつかblogにupする)

※ちなみに、書いてる事を単にまとめてるわけではないので、ご注意を。

ハイパフォーマンス ブラウザネットワーキング ―ネットワークアプリケーションのためのパフォーマンス最適化

ハイパフォーマンス ブラウザネットワーキング ―ネットワークアプリケーションのためのパフォーマンス最適化

16章 Server Sent Events

  • よく言われるのがSNSのTimelineの更新とかで使える仕組み
  • server sent eventsってwebsocketと被っている事もあって、中々目立たないですよね

server sent eventsの対応状況

  • caniuse
  • websocket同様androidIEが非対応で足ひっぱってきたが
  • androidは4.4から使える
  • IEは11でも未だに「使えない」

有名サイト

  • ちょっと気になったので、
  • 有名サイトでpush通知っぽい事をどういう技術で実現してるか、ざっくり調べてみた。
  • 2014年8月9日の状況
  • ざっくり見た感じなので、間違ってたらごめんなさい。

facebook

twitter

  • Timeline:ajax polling(数十秒)

gmail

  • ajax polling
  • 定期的にmailのpreloadしてて(多分cacheしてそう)、そのtimingでメールあれば、別xhr飛ばして取得してきてる

github

  • server sent events!!
    • 別host(live.github.com)とSSEで繋いでて、push来たら、本hostに通常のxhrでgetしてるっぽい

利用例

  • websocketも、server sent eventも、まだまだ珍しい状況。
  • 結局、いずれもIE/android対応遅かったので多くの機器でpolyfilする必要があり、複雑化を恐れたためか?
  • 今回ピックアップしてみた例の中では、server sent events利用してる所はgithub位だった。

実際、動かしてみる

sse

  • client側
source = new EventSource("stream");
source.addEventListener("message", function(e){
  // メッセージ表示処理
}, false);

sse

  • server側
// これはimageで色々省略してます。
var reqListener = function(req, res){
  res.writeHead(200, {"Content-Type":"text/event-stream"});
  res.write("id: 1234");
  res.write("data: some message");
}
http.createServer(reqListener).listen(8888);

要するに

  • front
    • EventSourceをnewすると、引数のパスにGETして通信開始
    • 後はevent bindingして処理を追記していく
  • back
    • responseのContentTypeにtext/event-stream
    • 決まった書式でresponse返す(data: ***)

Server-Sent Eventsの主要な要素

  • EventSourceインタフェース
    • DOMイベントとして取得できる
  • EventStream
    • 低レイテンシで単一接続で済む(consoleで確認してみよう)
    • sseはxhr上のstreamingでバッファ肥大化しない(通常のxhrと違って、メモリに溜め込まず消去されるらしい)

再接続

  • エラー時、自動再接続する機能
    • 試すと、確かにclientが勝手に再接続した。(復帰迄5,6sec位かかった)
  • 接続再開後、失われたメッセージの再配信する機能
    • これは、Last-Event-IDヘッダーをclientから渡す仕組みは確かにあるが、(p274)
    • それを見て、再送信させる云々はserver sideで自力で書かなくては行けない

polyfilライブラリ

  • 幾つかある様子
  • これとか
  • このpolyfilで決定版みたいなlibraryが無い点は注意(websocketといえば、socket.ioみたいな定番がsseは無い)

制限と課題

  • 制限
    • server -> clientのみ(逆は不可)
    • utf-8 文字のみ(バイナリはエンコードが必要で非効率)
  • 課題
    • NW中間装置がstreamをcacheするかも。そこからレイテンシ増加/接続破壊を引き起こす可能性あるらしい

まとめ

  • textのみの単純なpush通知なら、websocketよりsseの方が気軽(httpでxhrの延長なので)
    • serverも対応状況気にせず、実装もごちゃごちゃしない(さっきの中間装置はどうしようもないが)
  • IEandroidが足を引っ張ているので、polyfilは必須(定番っぽいのが無い)