satococoa's blog

主にサーバーサイド、Web 系エンジニアのブログです。Go, Ruby, React, GCP, ...etc.

WebSocket勉強会に参加しました

WebSocket勉強会に参加してきました。
いつものようにつらつらとメモや感想のまとめを。

時間のない方へはじめに結論(というか、盛り上がったポイント?)

さくらVPSとNode(Node.js) + Socket.IOを使えば「もう何も怖くない」by @kanreisa さん

業務向けにはIIJさんのIIJ GIOもよろしくね。

WebSocketを見てみよう

今までの双方向通信
  • AjaxによるPolling
  • Comet (代表: Long Polling)
WebSocket

標準化は現在進行形であり、仕様は以下のあたり

特徴は「全二重の双方向通信で、UTF-8の文字列 OR バイナリ(最近のレビジョン)のデータをやり取りできること。」

HTML5の一員として語られることが多いが、正確にはHTML5とは独立したものではある。
とは言え広義のHTML5の一員であると言えるため、この辺厳密な線引きはされていない様子。

既存のWebとの親和性を考慮して策定されており、最初のハンドシェイクをHTTPで行い、80番ポート(もしくは443ポート)を使用することで、既存のWeb-proxyを通過できるように工夫されている。
(しかし、現状ではFWは通過できるだろうけど、パケットを覗くproxyでは弾かれてしまうかも?)

各ブラウザの実行状況は資料のP.12からを見る方がいいと思いますが、サーバー側の実装が潤沢であるにも関わらず、クライアント側(Webブラウザ)などはまだまだこれからといった状態です。

ブラウザへの実装状況ですが、ほとんど現在は各ブラウザの開発版には搭載されている状況です。Firefox4ではデフォルトで無効化されていますが、それはちょっと前に問題になったプロトコル上のセキュリティに関する懸念があるからです。
ただ、それを利用した具体的な攻撃方法も見つかっていないため、それが見つかるまでは特に問題がないとみなされ、ChromeSafariではそのセキュリティに対する懸念のあると言われているレビジョンの実装が有効化されています。

現実に今からWebSocketを使おうと考えた場合は、Socket.IOや、PusherなどWebSocketが使えないクライアントではFlashを代替手段として使ってくれる、などのfallbackが考慮されているライブラリを使用するといいと思います。

個人的な感想ですが、Socket.IOはいいですね。Socket.IO使えば「もう何も怖くない。」

WebSocketのしくみ

スライドP.17からの内容です。2011/0525時点でIETF/W3Cの公開しているドラフト文書に基づいて、細かく説明してくださいました。

大まかな流れは以下のとおり。

1. Scriptを実行

URLについては、

  • schemeはws or wss(http, httpsのような対応関係)
  • portを含んでもよい(ws://example.com:3000/)
    省略されればws:なら80, wss:443
  • path, queryも含められる
    例) ws://example.com/chat/?room=1
  • fragmentを含んではならない
    ws://example.com/chat#room=1 はできない
2. HTTPでハンドシェイク

資料P.25を見ていただくのがいいかも。 リクエストの3行目、Upgrade: websocketが中身を覗くプロキシに弾かれてしまう、という声も会場からはありました。

プロトコルのレベルになると僕は全然知識が足らずにいまいち理解が出来ていないのですが、
"Wec-WebSocket-Key: 任意の文字列"を使用して認証を実現したりするようです。

また、仕様では明示的にCookie使用可とは書かれていませんが、リクエストヘッダの例として「例えばCookieとか、Sec-WebSocket-Protocolとか・・・」のような書き方がされているそうです。要はあとはアプリケーション側でなんとかしてってことですかね。

ここで"Sec-WebSocket-Protocol:"というのが出てきますが、これが前述のサブプロトコルです。
アプリケーションレベルで任意にプロトコルを定義して、サーバーから返されることが期待されるものを列挙してリクエストとして送り、サーバーがその中から使用するプロトコルを選択する、という仕組みだそうです。
意外とフリーダムな印象です。

あとはSec-WebSocket-Extensionsヘッダを使って圧縮などの拡張を使用できるそうです。

3. WebSocketでデータ転送

WebSocketはデータを転送する際、1つまたはそれ以上のフレームの連続としてデータを転送するそうです。 フレームが確実に届くことと、その順序はTCPなので保証されており、ブラウザから送られるペイロード(転送されるデータ本体)は必ずマスクされます。(暗号化とは違い気休め程度、という声もありました。)

また、資料P.35のペイロード長の定義を知っておくと、サブプロトコルの設計やデータ量の節約などに役に立つと思います。

4. 切断

サーバー・クライアントからcloseを送信しただけでは切断されず、必ずそれに対する返答を受信してから切断される仕組みだそうです。

補足

質疑応答の際にWebSocketも基本的にはSame-Originのポリシーとの説明がありましたが、実際はそうではないとの旨懇親会でご本人から補足がありました。
(別ドメインのWebSocketサーバーにもつなげるということ。)

まとめ

プロトコルのレイヤーの話は今まで殆ど分かっていませんでした。
アプリ開発者としてはSocket.IOなどに任せてしまう部分だとは思いますが、知っておかないとデバッグなどで困ることになるのかもしれません。
まともなWeb開発者ならHTTPのヘッダを確認することは普通ですし、その延長ですよね。

WebSocket事例紹介

「WebSocketを使うと無駄なヘッダーのやりとりが節約できます。」というのは知っていましたが、資料のP.14は必見です。
この条件で300万円/月の節約になると聞き、取り組むべき価値がかなり明確になりました。
接続数が多くなれば多くなるほど切実ですね。

僕が作ったアプリでも使っているPusherの紹介もありました。heroku使ってる人にはおすすめです。

発表された@MiCHiLUさんはWebSocket.JPというグループの立ち上げやShirasu.wsというWebSocketのフレームワークの開発なども行っているそうで、精力的に取り組まれている様子でした。

NonBlock Socket and Asynchronous I/O

Node(Node.js)などを語る際によく言われるノンブロッキングとか、非同期とかのあたりを分かりやすく整理してくださいました。

覚えておくこと3つ
  1. 並行処理
  2. 同期呼び出し・非同期呼び出し
  3. ブロッキングI/O・ノンブロッキングI/O
気をつけること

イベントハンドラ内はシングルスレッドなのでなるべく処理を軽くする。

スケールさせるには?
  • 複数サーバ立てる
  • Reverse Proxy / Load Balancer
lighttpd用モジュール

lighttpd用のWebSocketモジュールを作られているそうです。

簡単な設定ファイルを作るだけでWebSocketから、ローカルのTCPSocketを繋ぎ込むことができるモジュールで、実際にサーバー上のPostfixとブラウザをつないでSMTPがしゃべれるデモを見せて下さいました。

これを応用するとブラウザからSSHできたりしそうですね。(もう既にある?)

「さくらのVPSでnode.jsを使ってみよう」(仮)

軽妙な語り口で、随所でウケを取っていました。
デモも、さくらのVPS上にインストールしたDebianiPadから接続してコマンドを打つ、というスタイル。

Togetterを見るとその盛り上がりの一端が見えると思います。

Node(Node.js)をイチオシされていました。さらにSocket.ioを使えば「もう何も怖くない」

ブラウザのハードウェア対応の未来を探る

ustにこの部分、入っていますでしょうか。確認していませんが、デモをぜひ見てください。

仮想現実の中に入り込めるようなゲーム、面白そうですね〜。スト4みたいなものもできる時代が来るのでしょうか。

Websocket Communication

発表資料自体がWebSocketを使って作られていて、@kamiyamさんの手元のiPhoneでスライドを切り替えると、各参加者の画面上でもスライドが切り替わる、という仕組みでした。

また途中に盛りこんであったアンケートにも当然WebSocketを使われていて、回答が送信されるたびに数字が増えていくさまが面白かったです。

WebSocketでデバイス間連携

HTML5とか勉強会のスタッフをされたりしているそうです。

Jettyを使ってiPhoneからWindowsを操作したり、Keynoteを操作したりするデモを見せて下さいました。

Jettyを使った理由としては機能面(ライブラリの充実、exe可/app可の容易さ)を挙げていらっしゃいました。 Java.awt.Robotというライブラリを使うとマウスやキーボードの操作をエミュレートすることができ、Java Scripting APIを使用するとApple Script(等他の言語)を呼び出すことができたりするそうです。

また、ご自身の作られたWebSocketRemote(http://www.kanasansoft.com/weblab/2010/04/websocketremote00_1.html)で苦労した点についてもお話がありました。

懇親会

なぜかアジャイルについて語ったり、ゲーム業界とWeb業界のプロジェクトの進め方の違いについて語ったり、楽しい時間を過ごさせていただきました。

おいしい料理もたくさん出てきて、大満足でした。

最後に

今回の勉強会は非常にテーマが幅広く、WebSocket自体のプロトコルについての話から採用事例、デモまで上から下のレイヤーまでカバーされていました。
そのため参加されている方もWeb開発者が半数程度、という普段僕が参加する勉強会とはまた違った雰囲気で、とても刺激になりました。

朝〜夜までという長丁場でしたが、熱気に満ちた大変ためになる勉強会でした。主催者の方々、講師の方々、どうもありがとうございました。

蛇足ですが、ボランティアとして朝イチの受付で懇親会のお金集めをさせていただいていたのが僕です。
慣れないもので手際があまり良くなかったかと思いますが、ご勘弁ください。