パフォーマンスチューニング
Socket.IOサーバーのパフォーマンスを向上させるためのヒントを以下に示します
複数ノードへのスケーリングにも興味があるかもしれません。
Socket.IOレベルで
ほとんどの場合、Socket.IO接続はWebSocketで確立されるため、Socket.IOサーバーのパフォーマンスは、基盤となるWebSocketサーバーのパフォーマンス(デフォルトではws
)に強く関連付けられます。
ws
ネイティブアドオンをインストールする
ws
には、特定の操作を改善する2つのオプションのバイナリアドオンが付属しています。プリビルド済みのバイナリは、最も一般的なプラットフォームで利用できるため、必ずしもマシンにC++コンパイラーをインストールする必要はありません。
- bufferutil:WebSocketフレームのデータペイロードのマスキングやアンマスキングなどの操作を効率的に実行できます。
- utf-8-validate:仕様で要求されているように、メッセージに有効なUTF-8が含まれているかどうかを効率的に確認できます。
これらのパッケージをインストールするには
$ npm install --save-optional bufferutil utf-8-validate
これらのパッケージはオプションであり、WebSocketサーバーは利用できない場合、Javascriptの実装にフォールバックすることに注意してください。詳細については、こちらをご覧ください。
別のWebSocketサーバー実装を使用する
たとえば、eiowsパッケージを使用できます。これは、(現在非推奨の)uwsパッケージのフォークです。
$ npm install eiows
次に、wsEngine
オプションを使用します。
const { createServer } = require("http");
const { Server } = require("socket.io");
const httpServer = createServer();
const io = new Server(httpServer, {
wsEngine: require("eiows").Server
});
カスタムパーサーを使用する
Socket.IO接続を介してバイナリデータを送信する場合、カスタムパーサー(msgpackに基づくものなど)を使用すると、デフォルトでは各バッファが独自のWebSocketフレームで送信されるため、興味深い場合があります。
使用法
サーバー
const { createServer } = require("http");
const { Server } = require("socket.io");
const parser = require("socket.io-msgpack-parser");
const httpServer = createServer();
const io = new Server(httpServer, {
parser
});
クライアント
const { io } = require("socket.io-client");
const parser = require("socket.io-msgpack-parser");
const socket = io("https://example.com", {
parser
});
最初のHTTPリクエストを破棄する
デフォルトでは、各セッションの最初のHTTPリクエストへの参照がメモリに保持されます。この参照は、たとえばexpress-session
を使用する場合に必要ですが(こちらを参照)、メモリを節約するために破棄できます。
io.engine.on("connection", (rawSocket) => {
rawSocket.request = null;
});
以前
その後
OSレベルで
OSを調整して多数の接続を受け入れる方法については、多くの優れた記事があります。たとえば、こちらの記事またはこちらの記事をご覧ください。
負荷テストでSocket.IOサーバーをテストしていると、次の2つの制限に達する可能性があります。
- 最大ファイルオープン数
1000を超える同時接続(新しいクライアントが接続できない)を実行できない場合、最大ファイルオープン数に達している可能性があります。
$ ulimit -n
1024
この数を増やすには、次の内容で新しいファイル/etc/security/limits.d/custom.conf
を作成します(root権限が必要です)
* soft nofile 1048576
* hard nofile 1048576
次に、セッションをリロードします。新しい制限が更新されるはずです
$ ulimit -n
1048576
- 利用可能なローカルポートの最大数
28000を超える同時接続を実行できない場合、利用可能なローカルポートの最大数に達している可能性があります。
$ cat /proc/sys/net/ipv4/ip_local_port_range
32768 60999
この数を増やすには、次の内容で新しいファイル/etc/sysctl.d/net.ipv4.ip_local_port_range.conf
を作成します(これもroot権限が必要です)
net.ipv4.ip_local_port_range = 10000 65535
注:下限として10000
を使用しました。これにより、マシン上のサービス(PostgreSQLサーバーの場合は5432
など)で使用されるポートは含まれませんが、より低い値(最大で1024
)を完全に使用できます。
マシンを再起動すると、55kの同時接続(着信IPごと)に快適に到達できるようになります。
こちらもご覧ください