Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Socket.IO 1.0の変更点・内部的な話
Search
Naoyuki Kanezawa
June 23, 2014
Programming
9.4k
20
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Socket.IO 1.0の変更点・内部的な話
socket.io 1.0と0.9の比較や内部実装について。 node学園#13
Naoyuki Kanezawa
June 23, 2014
More Decks by Naoyuki Kanezawa
See All by Naoyuki Kanezawa
Introducing Now and Next.js
nkzawa
12
5.6k
WebSocketの圧縮機能とSocket.IO
nkzawa
5
9.4k
Socket.IO 1.0 Client for Javaの紹介
nkzawa
5
1.9k
Other Decks in Programming
See All in Programming
[PyCon KR 2026] More Variants, More Diversity for AI Accelerators
achimnol
0
110
承認済みなのに差戻しできてしまうバグ、型で潰せます
shinchit
0
110
jsmini JavaScript Engine を作ってみた話
yosuke_furukawa
PRO
0
350
言葉の格闘技のススメ~紙とペンと言葉から始める、キャリアの描き方~
progresscicada
2
180
Jindong: Introducing Declarative Haptics in Compose Multiplatform
l2hyunwoo
0
130
tsc.rip を支える技術 / Kyoto.なんか #8
susisu
0
280
仕様駆動開発へのトライを機に チームに適合する手法を模索し続けている話
freee
PRO
0
620
S3 を使うアプリケーションをローカル完結で動かすことに全力を注いでみた / Running S3 Apps Offline
contour_gara
0
610
Detecting Compromised CI with eBPF and Cilium Tetragon
lizrice
0
260
AIに既存システムを理解させる技術 ~レガシーを見捨てないハーネスエンジニアリング入門~
ochtum
0
150
<title><a id="</title>君はこのHTMLをパースできるか"></a></title> #雑LT_study
pizzacat83
0
180
AWS Transform Customによる Spring Boot 2.xから4.xへのVerUp
satoshi256kbyte
2
100
Featured
See All Featured
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.4k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
180
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
360
A Modern Web Designer's Workflow
chriscoyier
698
190k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.5k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.5k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
390
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
280
Building an army of robots
kneath
306
46k
BBQ
matthewcrist
89
10k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
620
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.7k
Transcript
Socket.IO 1.0の変更点、内 部的な話 Node学園#13
自己紹介 github: nkzawa twitter: nkzawa socket.io, engine.ioなどにコントリビュートしたり、 socket.io関連モジュールをつくったり。
アジェンダ 1. Engine.IOとUpgrade 2. Middleware 3. バイナリサポート 4. Adapter 5.
プロトコル
Engine.IO と Upgrade
engine.io • トランスポートの違いを吸収して、websocketと同等の機能 を提供するライブラリ。 • socket.io 1.0には名前空間やルーム、自動再接続などの 高レベルな機能のみ実装され、メッセージの送受信は engine.ioを通して行われる。 •
socket.io 0.9で採用されていたfallback方式ではなく upgrade方式でトランスポートを切り替える。
fallback 1. 最初にwebsocketで接続を試みる。 2. 接続できたら終了。 3. 接続できなかった場合、初期設定で最低10秒間タイムアウ トを待つ。 4. タイムアウトしたら、改めてpollingで接続を行う。
=> websocketが使えない場合の初回接続速度に問題があっ た。
upgrade 1. httpのgetリクエストを行い、pollingの接続を確立させる。 2. upgradeできるか判定。設定次第でupgradeは行われず終 了。 3. pollingを維持したまま、並列にwebsocketで通信しパケット の交換ができるかどうかまで試す(probe)。 4.
websocketがつながったらpollingが止まるのを待ち(メッ セージのロスを防ぐため)、メインのトランスポートを切り替 える。
サポートされるトランスポート • websocket • polling ◦ xhr ◦ jsonp ※polling時はxhrが優先的に使用される。
flashsocket ? 公式にはサポートされなくなった。flashsocketに限らず、別のト ランスポートが必要な場合は自作して追加する。 “removed flashsocket, moving to userland” https://github.com/Automattic/engine.
io/commit/10261c52119f2912b72b55bec4df87d91b180525
upgrade関連オプション(client側) transports: [‘polling’, ‘websocket’] 使用するトランスポートを順番に設定する。[‘websocket’] と すると最初からwebsocketで接続することもできる。 rememberUpgrade: false 一度upgradeに成功した後に再接続すると、upgradeプロセ
スを飛ばしてwebsocketで接続する。SSLの時などに有効 にするとよいらしい。
Middleware
middleware ハンドシェイクから接続までの間に、処理を挿入する仕組み。 expressのmiddlewareと似たようなもの。 io.use(function(socket, next) {});
0.9では 0.9ではauthorizationで同様のことができたが、あくまで認証用 の機能で拡張性は低かった。 io.set(‘authorization’, function(handshakeData, fn) { // 認証失敗 fn(null,
false); });
1.0の認証 setメソッドとauthorizationは廃止(後方互換のため残されては いる)。代わりにmiddlewareを使って認証する。 io.use(function(socket, next) { // 接続を閉じる next(new Error(‘not
authorized’);); });
ハンドシェイクデータ ハンドシェイク時のrequestオブジェクトにアクセスでき、そこか らcookieのパースやセッションの復元などが可能。 io.use(function(socket, next) { console.log(socket.request); next(); });
// expressのmiddlewareを使ってcookieをパースする var cookieParser = require(‘cookie-parser’)(‘my secret’); io.use(function(socket, next) {
var req = socket.request; var res = {}; // ダミーのレスポンス cookieParser(req, res, next); }); io.on(‘connection’, function(socket) { console.log(socket.request.cookies); });
ネームスペース middlewareはネームスペース単位。 // デフォルトネームスペース。次の二つは同じ意味。 io.use(function(socket, next) {}); io.of(‘/’).use(function(socket, next) {});
// foo ネームスペース io.of(‘/foo’).use(function(socket, next) {});
実行順序 全てのクライアントは、デフォルトネームスペース(’/’)へ必 ず最初に接続され、’/’ のmiddlewareが実行される。 cookieパーサのように、常に先に実行したいmiddlewareは ‘/’ へ登録する。
// クライアント var socket = io(‘http://localhost:3000/foo’); // サーバ io.use(function(socket, next)
{ console.log(‘first’); // 先に実行される next(); }); io.of(‘/foo’).use(function(socket, next) { console.log(‘second’); // 後で実行される next(); });
バイナリサポート
バイナリサポート 1.0からバイナリデータを送受信できるようになった。オブジェク トや配列に埋め込むんだり、複数バイナリを同時送受信も可 能。 socket.emit(‘event’, new Buffer([0, 1, 2]));
examples // オブジェクトに埋め込み socket.emit(‘event’, {data: new ArrayBuffer(10)}); // 複数バイナリ socket.emit(‘event’,
[binary1, binary2]); // acknowledge socket.on(‘event’, function(callback) { callback(new Buffer([1, 2, 3])); });
0.9でバイナリを扱う 0.9でもバイナリをbase64エンコードした文字列として送受信す ることはできた。ただし、エンコード/デコード処理が入り、データ サイズも増加するため効率はよくない。 socket.emit(‘event’, buffer.toString(‘base64’));
サポートされるデータ形式 • Buffer (node) • ArrayBuffer (node, browser) • Blob,
File (browser)
バイナリ送信できるトランスポート • ◯ websocket • ◯ XMLHttpRequest Level 2 •
☓ 古い仕様のwebsocket • ☓ XMLHttpRequest • ☓ JSONP ※バイナリ送信をサポートしないトランスポートでも、base64エンコードされた文字列 として透過的にデータを送受信できる。
バイナリの扱いに注意 データサイズに制限はないが、メモリへ読み込むので、大きな ファイルの配信などには向かない。 この問題を解決するために、別モジュールによるstream送信の サポートが計画されている。
Adapter
Adapter 複数のサーバ間でメッセージをbroadcastする時に 使用される。0.9にあったStoreの代替。 io.adapter(Adapter);
socket.io-redis 0.9にあったRedisStore相当のadapter。socket.io本体には同 梱されていないので、別途インストールが必要。 var redis = require(‘socket.io-redis’); io.adapter(redis({host: ’localhost’, port:
6379}));
Storeとの違い • Storeのget/set 相当のデータ共有機能がなくな りシンプルに。Adapterが扱うのはbroadcastの み。 • 内部的に使っていたpublish/subscribeがなく なってスケールしやすい設計に。
socket.io 0.9のサーバ間共有設計 クライアントの接続データ(handshakeデータ, 所属ルーム等) は、Storeを通して他のサーバへ通知され保存される。 それぞれのサーバが、他サーバに接続しているものを含む全て のクライアントデータ(の一部)を処理し、保持するためスケール しにくい。
例: socket.io 0.9サーバ10台に、それぞれ1万クライアントが 同時接続する場合。 各サーバそれぞれで10万クライアントのデータが処理・保持さ れる。サーバを増やしても、一つのサーバが処理するデータ数 は変わらず、同時接続数に比例して増える。 サーバA: 10万 サーバB:
10万 … ※あくまでデータの一部なので全くスケールしないわけではないと思われる。
socket.io 1.0のサーバ間共有設計 各サーバは一切データ共有を行わない。 1.0のAdapterでは、broadcastしたパケットとそのオプション データだけが通知され、サーバには何も保存されないためス ケールしやすい。
例: socket.io 1.0サーバ10台に、それぞれ1万クライアントが 同時接続する場合。 各サーバは自身に接続している1万クライアントのデータのみを 処理・保持する。サーバを増やすことで、一つのサーバが処理 するデータ数を減らすことができる。 サーバA: 1万 サーバB:
1万 ...
プロトコル
プロトコルの変化 socket.ioの構成変更や機能追加に伴い、プロトコ ルの大幅な更新が行われた。 • トランスポート層(engine.io)の分離 • バイナリサポート
0.9のパケット コロン区切りのメッセージ [type] : [id] : [namespace] : [data] 例:
5::/nsp:{"name":"foo","args":["hi"]}
0.9のペイロード pollingで一度に複数のパケットを一括送信するの に使用される。\ufffd 区切りでデータ長 +パケットを 連結して繰り返す。 \ufffd [length] \ufffd [packet]
... 例: \ufffd32\ufffd5:::{"name":"foo","args":["hi"]}\ufffd ...
1.0のパケット 区切り文字とJSONのキー名がなくなり効率的に。 データはutf8エンコードされる。 [engine.io type] [type] [namespace] , [data] 例:
42/nsp,["foo","hi"]
1.0のバイナリを含むパケット バイナリ数が追加。バイナリデータはプレースホル ダで置き換えられ、別のパケットとして送られる。 [engine.io type] [type] [binary数] - [namespace] ,
[data] 例: 451-/nsp,["foo",{"_placeholder":true,"num":0}]
1.0のペイロード バイナリ送信をサポートするtransportでは、文字列も全てバイ ナリに変換される。パケットがutf8エンコードされるのはこのた め。 [0(string), 1(binary)] [length(一桁づつ)] 255 [packet] ...
例: [00 02 05 ff 34 32 2f 6e 73 70 2c 5b 22 65 63 68 6f 20 62 61 63 6b 22 2c 22 68 69 22 5d]
1.0のペイロード(文字列) バイナリ送信をサポートしないtransportでは、文字 列のまま送信。バイナリはbase64エンコードされ る。 [length] : [packet] ... 例: 19:42/nsp,["foo","hi"]
プロトコルの変更による影響 socket.io 0.9のプロトコルを実装していた別言語 のsocket.ioサーバ・クライアントは一切使用できな い。 => ユーザが0.9から1.0にアップデートする際の最 も大きな障害になると思われる。
まとめ • engine.ioでより安定したsocket通信ができます。 • middleware便利。モジュールを作って公開しよう。 • バイナリも送受信できるようになった。 • adapterでスケールしやすいアーキテクチャに。 •
0.9から1.0への移行は難しくない。プロトコルの違いには注 意。
thanks!