問題:ファイル記述子の上限への到達負荷の高いNginxサーバーでは、突然トラフィックの受け入れが停止したり、Node.jsやPHP-FPMなどのバックエンドサービスとの通信に失敗したりすることがあります。/var/log/nginx/error.logを確認し、(24: Too many open files)という重大なエラーが表示されている場合、サーバーのリソースが不足しています。これは通常、Linuxがネットワークソケットからログファイルに至るまで、ほぼすべてのものを**ファイル記述子(File Descriptor: FD)**として扱うために発生します。
デフォルトでは、多くのLinuxディストリビューションで1つのプロセスあたりのオープンファイル数が1,024に制限されています。デスクトップ用途では安全ですが、5,000人の同時接続ユーザーを処理する高性能Webサーバーでは、この制限に数ミリ秒で達してしまいます。これを修正するには、OS、サービスマネージャー、およびNginx自体の制限を引き上げる必要があります。
ステップ1:現在の制限を確認するまず、実行中のNginxワーカープロセスに適用されている実際の制限を確認します。プロセスID(PID)を特定し、/procファイルシステムを介してその制限を直接調べることができます。
# 実行中のNginxワーカーのPIDを特定する
ps aux | grep nginx
# そのPID(例:1234)の制限を確認する
cat /proc/1234/limits | grep "Max open files"
「Soft Limit」が1024と表示されている場合、そこがボトルネックです。この数値は現代のプロダクション環境のワークロードに対しては低すぎます。
ステップ2:OSレベルの制限を調整するOSがNginxユーザーに対してより多くの記述子を割り当てられるように許可を与える必要があります。/etc/security/limits.confファイルを開き、これらのグローバルな境界を定義します。
sudo nano /etc/security/limits.conf
末尾に以下の行を追加します。Nginxサービスが実行されているユーザー(通常はwww-dataまたはnginx)を使用してください。
nginx soft nofile 65535
nginx hard nofile 65535
これにより、制限が高性能システムの標準的な値である65,535に設定されます。ただし、現代のシステムではこのファイルの設定だけでは不十分です。
ステップ3:Systemdの設定を更新する現代のLinuxバージョン(Ubuntu 18.04以降、CentOS 7以降など)はSystemdを使用しており、バックグラウンドサービスに対してはlimits.confが無視されることがよくあります。そのため、Nginxユニットに対して高い制限を許可するよう、Systemdに明示的に指示する必要があります。
パッケージの更新時に設定が上書きされないよう、オーバーライドファイルを作成します。
sudo mkdir -p /etc/systemd/system/nginx.service.d/
sudo nano /etc/systemd/system/nginx.service.d/override.conf
以下の構成を貼り付けます。
[Service]
LimitNOFILE=65535
保存後、Systemdデーモンをリロードして新しい指示を認識させます。
sudo systemctl daemon-reload
ステップ4:Nginxのワーカー制限を設定するOSが65,000個のファイルを許可していても、Nginxに明示的に指示しない限りそれらは使用されません。Nginxの内部設定を新しいシステム制限に合わせる必要があります。
/etc/nginx/nginx.confを開き、トップレベルにworker_rlimit_nofileディレクティブを追加します。
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535; # OSの制限に合わせる
events {
worker_connections 16384; # rlimit_nofileより十分に低い値に設定する
}
http {
...
}
2:1の法則: worker_rlimit_nofileは、常にworker_connectionsの少なくとも2倍に設定してください。プロキシされた各リクエストは、クライアント接続用とアップストリームバックエンドへの接続用の少なくとも2つのファイル記述子を使用するためです。
ステップ5:適用と確認サービスを再起動する前に、設定ファイルの記述ミスをチェックします。
sudo nginx -t
テストに合格したら、Nginxを再起動してすべての変更を適用します。
sudo systemctl restart nginx
最後に、新しいプロセスに対して新しい制限が有効であることを確認します。以下のコマンドを実行して、最新のワーカーPIDを確認します。
NEW_PID=$(pgrep -n nginx)
cat /proc/$NEW_PID/limits | grep "Max open files"
制限が65535として反映されているはずです。これで、サーバーは何万もの同時接続を問題なく処理できるようになりました。

