メインコンテンツにスキップ
バージョン: 4.x

パフォーマンスチューニング

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;
});

以前

Memory usage before

その後

Memory usage with request discarded

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ごと)に快適に到達できるようになります。

こちらもご覧ください