電脳麻将 は さくらVPS で運用しており、麻雀サーバー もここにあります。 最繁時には 60人程度の方が卓を囲んだ実績 はあるのですが、どこまで受け入れることが可能か調べてみました。 もし4000人同時接続できれば 現在の天鳳レベル のトラフィックと言えるでしょう。
対象サーバはさくらVPSの メモリ1GB のモデルです(年額9,680円のモデル)。 ここに外部からアクセスし、実際にネット対戦を行います。 麻雀サーバーには ボットの機能 もありますが、ボットは1接続1プロセスなのでこれを素直に使うとサーバーよりも先にクライアントに負荷がかかってしまいます。 なので 複数のボットを1プロセスで並行して実行 できるようなドライバを作成し、それを複数台動作させて性能を検証してみることとします。
まずは開発用のMacBook Air(以下MacBook)で麻雀サーバーを起動し、ドライバも同じMacBook上で動作させ測定してみます。 MacBookなら さくらVPSよりかなり高スペックなので、1024接続くらいなら簡単にさばいてしまうことが予想できますね。
ドライバは以下の流れで動作します。
ボットで実装していたのは招待された対局者の処理だけですので、ルームの作成と、4人そろったか検知しゲームを開始する部分を新たに作りました。 ログアウトは確実に行う必要があります。これを行わないとセッションデータが残ってしまい14日間回収されないからです。
まずはこれで4接続、8接続、16接続と順に試したところ、128接続くらいで問題に気づきました。 まずドライバの動作がすさまじく重い。CPUのほとんどをドライバが占有する重さです。 次に卓がそろわない。順次卓を生成する流れにしていたので、最後の卓が立つ頃には最初の卓が終わってしまっている状態になりました。
動作の重さですが、ボットは最新版の麻雀AIを使っているので考えてみれば当たり前です。 最新版のAIは1000半荘の実行に8時間かかるのですから、128接続32卓の実行でも15分くらいはかかります。 つまり4000接続1000半荘を実行しようとしたら8時間分のCPUを使いますし、当然最初の卓は終了している訳です。
今回は麻雀としての動作が正しければよく、強さは求めないので過去のAIを使うことにしましょう。 「先読み」を入れる前のAIなら半荘を1~2秒で実行します。 また、卓をそろえるために、先に説明した手順をすべて並行して実行することにします。 つまり、まず全員がログインし、次に全員がWebSocketを作成、全員分の卓組を終えて同時に対局を開始するという方法です。 すべての卓を同時に実行できるのであれば半荘は長すぎます。終了もできるだけそろえたいので東風戦、連荘なし、トビなし、途中流局なしの ルールで実行するよう修正します。
修正したドライバで4096接続まで実験しました。 MacBookでは問題なく動作し、測定中に対局してみてももたつきは感じません。これなら さくらVPSでもいい結果が出るかもしれません。
さくらVPSでは、フロントエンドにリバースプロキシの nginx がおり、バックエンドにNode製の麻雀サーバーを配置する構成となっています。 まずはバックエンドの麻雀サーバーに直接アクセスして性能を測定します。 2048接続から試してみましたが、WebSocketを1300接続したあたりからネットワークが不安定になり新たな接続が行えません。 さくら側のDoS検知かもしれないと思い*1接続間隔を 150ms にまで落として対応しました。
2048接続での メモリ使用量は150MBほど でまだ余裕がありますが、CPU使用率が80% となっており限界かもしれません。 同時に私もボットと打ってみましたが大きなもたつきは感じませんでした。 ところが私が対戦を終えてみると負荷試験側は全て対局が終わっていました。 そうです、負荷試験の打牌速度が早すぎるのです。測定したみたところ東風戦を2分程度で打ち切っています。 これではいくら何でも早すぎてす。東風戦に8分程度かけるよう各摸打に1秒のディレイを追加しました。 この条件なら4096接続も行けそうです。
次に4096接続を試したのですが、3800接続を超えたあたりからまたネットワークが不安定になり、サーバーに対する新しい接続ができなくなってしまいました。
AIの薦めでに久々に dmesg を見てみます。
$ dmesg -T | tail -100
以下のメッセージが出ていました。
[Sat Aug 15 00:22:15 2026] nf_conntrack: nf_conntrack: table full, dropping packet
原因が特定できました。nf_conntrack のテーブルサイズが小さいのです。 net.netfilter.nf_conntrack_max に設定があるとのことなので確認してみます。
$ sysctl net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_max = 6144
これが妥当かよくわからないので、以前メインで使っていたCentOSの値を調べると 31704 でした。 同じ値を設定します。
$ sudo sysctl -w net.netfilter.nf_conntrack_max=31704
net.netfilter.nf_conntrack_max = 31704
これだけだと再起動時に戻ってしまうので /etc/sysctl.conf に値を追加します。
net.netfilter.nf_conntrack_max = 31704
一応再読み込みしておきましょう。
sudo sysctl -p
実は1300接続での問題も同じ原因だったのです。 つまりWebSocket接続の「手加減」は意味のない調整だったということです。 再度調整し、CPU使用率的に負荷をかけすぎない 40ms ごとの接続に修正しました。
4096接続での結果は、メモリ使用量250MB、CPU使用率60% でした。 合格です!同時に対局してもときどきもたつく程度です。
では最後にリバースプロキシの nginx を通す実際の運用形式で測定しましょう。
nginxが受付可能な接続数は、設定値 worker_connections の値を各workerプロセスごとに使用します。デフォルトでは 1024 と設定されていました。 さくらVPSメモリ1GBは2コアなので worker は2つ、1024 × 2 = 2048 接続まで許容するということになります。 バックエンドへの接続もあるのでWebSocktの1接続あたり2消費します。つまり1024接続未満ということになります。
実際に1024接続を試してみると 1000接続あたりで動作が不安定になりました。
error.log を見ると
2026/08/15 14:30:01 [crit] 1021142#1021142: accept4() failed (24: Too many open files)
という出力があり、ファイルオープン数の上限(ソケットもファイルと数える)に達していることがわかります。
ならば worker_connections の値を変更すればいいかというと、そう単純ではありません。 Linux には各プロセスごとにファイルオープン数の制限値があり、そのデフォルト値は ulimit で確認することができます。
$ ulimit -n
1024
しかしこれはあくまでデフォルト値であり引き上げることができます。
具体的にどのように制限がかかっているかは /proc/ 配下のファイルで確認できます。
麻雀サーバーは以下の値となっていました(1506566はプロセスID)。
$ cat /proc/1506566/limits|grep 'Max open files'
Max open files 524288 524288 files
おそらく node インタプリタが引き上げているのでしょう。道理で4096接続できた訳です。
一方nginxのworkerプロセスは
$ cat /proc/1021142/limits | grep 'Max open files'
Max open files 1024 524288 files
でした。デフォルト値のままですね。
nginx の制限値を変更しましょう。 nginxはsystemdから起動されるので、その設定ファイルを変更するのですが、インストールして更新するようなパッケージの場合は以下のコマンドで差分を設定するようです。
$ sudo systemctl edit nginx
以下の行を追加します。
[Service] LimitNOFILE=524288
変更を有効にします。
$ sudo systemctl daemon-reload
$ sudo systemctl restart nginx
変更されました。
$ cat /proc/1089678/limits | grep 'Max open files'
Max open files 524288 524288 files
これで /etc/nginx/nginx.conf の変更が有効になりました。
worker_connections 8192;
むやみに大きくしても意味がないと思うので、8192 としてみました。
設定が正しいか確認し、再読み込みさせます。
$ sudo nginx -t
$ sudo systemctl restart nginx
それではいよいよリバースプロキシの nginx を通す実際の運用形式で4096接続の負荷を測定しましょう。
結果は nginx を通さないときと同じ メモリ使用量250MB、CPU使用率60% でした。 さくらVPSのメモリ1GBモデルでも天鳳並みのトラフィックを捌くことができることが確認できました。大変満足です!
電脳麻将の 麻雀サーバー は誰でも使えるように公開していますので、ぜひ試してみてください。 あ、性能測定じゃないですよ。負荷をかけるようなアクセスはご遠慮ください😁