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.3k
Socket.IO 1.0 Client for Javaの紹介
nkzawa
5
1.8k
Other Decks in Programming
See All in Programming
はてなアカウント基盤 State of the Union
cockscomb
1
1.3k
1B+ /day規模のログを管理する技術
broadleaf
0
130
20260623_Loop Engineeringで自分の分身の問い合わせBotを作る
ryugen04
0
190
エンジニア向け会社紹介/Findy Company Profile
findyinc
6
360k
ECSアプリログをFireLensでコスト削減しようとしたけど諦めた話 in Fargate×Node.js
akihisaikeda
2
4.2k
AI時代の仕事技芸論〜ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ(スクフェス仙台 2026バージョン)
kuranuki
0
550
SLOをサービス品質の共通言語にするために 取り組んできたこと
wakana0222
0
450
コーディングルールの鮮度を保ちたい for SRE NEXT 2026 / keep-fresh-go-internal-conventions-sre-next-2026
handlename
0
140
Creating Composable Callables in Contemporary C++
rollbear
0
200
Claude Opus 4.6以後の受託開発エンジニアの変化(Claude Code開発ノウハウ大公開スペシャルbyクラスメソッド)
iidatakuma
1
410
どこまでゆるくて許されるのか
tk3fftk
0
460
霧の中の代数的エフェクト
funnyycat
1
320
Featured
See All Featured
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
380
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
440
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
210
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
1.9k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
630
Facilitating Awesome Meetings
lara
57
7k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
590
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
290
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2k
Writing Fast Ruby
sferik
630
63k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.1k
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!