がどのようなものかを示す。 ファイル記述子の制限 サーバー上の接続、ファイル、ソケットを制限することで、パフォーマンスが決まります。私は、サービスが負荷で失敗する前に、制限を増やし、需要を測定し、EMFILEのエラーを防止するための明確な措置を講じています。.
中心点
すぐに行動に移せるように、最も重要なことをまとめてみた。 レバー FDリミットを最適化する:
- 原因すべてのソケット、すべてのファイル、すべてのDB接続がFDを消費する。.
- 症状HTTP 500、EMFILEメッセージ、ブロックされたI/O、サービスのクラッシュ。.
- 測定ulimit、/proc/limits、file-max、lsofで明確になる。.
- 最適化limits.conf、systemd、sysctlのリミットを上げる。.
- セキュリティレート制限とモニタリングにより、高リミットを確保する。.
ファイルディスクリプタとは何か?
ファイルディスクリプタは単純な整数です。 識別子, これは、カーネルがプロセスごとに開いているファイル、ソケット、パイプ、デバイスを参照するために使用する。各プロセスにはソフトリミットとハードリミットがあり、システム全体のグローバル最大値もあります。 希少性 を防ぐ必要がある。デフォルトでは、1プロセスあたり1024個のFDしか利用できないことが多く、トラフィックの多いウェブサイトやAPIゲートウェイ、チャットバックエンドなどではすぐに手狭になってしまう。 負荷ピーク が強まる。プロセスが限界に達すると、新しい接続は失敗し、ワーカーはファイルを開けなくなり、ログはEMFILEでいっぱいになる。 応答時間 を拡張した。PHP-FPM やキャッシュバックエンド、ログファイル、リバースプロキシなどは、 リクエストごとに複数のハンドルを使用するようなセットアップでは特に重要になります。 バウンダリー ブロックに入った。.
症状を認識し測定する
リミットがきつすぎる最初の兆候は、しばしば次のように見られる。 HTTP-500 原因がはっきりしない、応答が遅い、個々のサービスが散発的に再起動する。開いているファイルが多すぎる」というような典型的なログエントリーは、EMFILEを示し、即座に次のことを知らせる。 アクションの必要性. .私はまず、局所的なボトルネックとシステム全体の問題を区別するために、プロセスに関連する限界と消費電流をチェックします。 原因 より正確にはこのコンパクトなガイドは、体系的な導入に適している。 サーバー制限ガイド, 調整ネジの概要を知りたい場合。 ステップ を計画している。負荷プロファイルと同様に、測定値は仮定に勝るからだ。 変更.
# 現在のシェルのソフトリミットとハードリミット
ulimit -n
ulimit -Hn
# プロセスの制限をチェックする
cat /proc//limits | grep "ファイルを開く"
# システム全体のステータス
cat /proc/sys/fs/file-nr # open | free | maximum
cat /proc/sys/fs/file-max # グローバル最大値
# プロセスごとの消費量の概算
lsof -p | wc -l
限度額の確認と主要数値の解釈
私はプロセス関連とグローバルな境界を厳密に区別し、的を射た方法でボトルネックを特定できるようにしている。 排除する を単に移動させる代わりに使用する。ハードリミットはセッションの増加の上限を設定し、fs.file-maxとfs.nr_openはグローバルフレームを定義する。 定員 ホストのRAMとワークロードがこれをサポートし、かつ以下のような条件が揃っていれば、1プロセスあたり少なくとも65535個のFDを許可するのが、試行錯誤の経験則です。 負荷 を知っている。同時に、現実的な高負荷のシナリオで、アクティブなワーカー、子プロセス、ネットワーク接続の合計がグローバルな フレーム値 が残る。これらの数字を明確に把握することで、無計画な増加を防ぎ、システムの完全性を管理下に置くことができる。 圧力.
| コマンド/パス | 機能 | 何に注意すべきか |
|---|---|---|
ulimit -n / -Hn | 現在のセッションのソフト/ハードリミット | ハードリミットは、以下の上限を設定する。 リフティング |
/proc//リミット | プロセスごとの制限とオープンファイル | などのデーモンにとって重要である。 nginx/php-fpm |
/proc/sys/fs/file-max | すべてのFDのグローバル最大値 | プロセス量と RAM フィット |
/proc/sys/fs/file-nr | オープン、無料、最大人数 | 負荷テストの傾向と ピーク チェック |
lsof | オープンハンドルを表示 | ワーカー/スレッドあたり 消費済み FDの測定 |
FDリミットを一時的および恒久的に調整
迅速なテストのために、私はulimitを使ってより高い値を設定する。 ソフトリミット, 永続的なルールを定義してサービスを再起動する前に。その後、/etc/security/limits.confに適切なエントリーを書き、systemdのオーバーライドを追加し、ターゲットとした 負荷テスト. .重要:サービス利用者が正しくなければ、増額効果はありません。 問題 は負荷がかかると現れます。また、多くのワーカープロセスが一緒にシステムリミットを超えないように、グローバルリミットを調整しています。 アキュミュレイト レット。プロセス側とシステム側が一体となって初めて、構成は実際の高負荷シナリオに耐えることができ、次のような事態を避けることができる。 イーエムファイル.
# 一時的 (ログアウト/再起動まで)
ulimit -n 65535
# システム全体 (再起動するまで、または sysctl.conf で恒久的に)
sudo sysctl -w fs.file-max=2097152
# 常設(ウェブサーバーユーザーの例)
echo -e "www-data soft nofile 65535nww-data hard nofile 65535n* soft nofile 65535n* hard nofile 65535" | sudo tee -a /etc/security/limits.conf
# systemdサービス(nginxなど)
sudo mkdir -p /etc/systemd/system/nginx.service.d
cat <<'EOF' | sudo tee /etc/systemd/system/nginx.service.d/limits.conf
[サービス]
リミットNOFILE=65536
EOF
sudo systemctl daemon-reload && sudo systemctl restart nginx
カーネルパラメータを正しく設定する
私は、fs.file-maxとfs.nr_openを一緒に検証することで、カーネルが十分なファイル数を確保できるようにしている。 バッファ をピーク負荷のために使用する。プロセスごとのリミットを増やすだけでは、グローバルなリミットにぶつかり ボトルネック システム・レベルでの典型的なピーク負荷とグローバル値との間にギャップを維持することは理にかなっている。 リスクピーク を減衰させることができる。システム全体のチューニングに関する詳細は、以下の記事を参照してほしい。 カーネル・チューニング, OSを徹底的にカスタマイズするためのツールとして使っている。 チェックリスト を使用する。変更後、パラメーターを再読み込みし、file-nrを再度チェックし、すべてのサービスが新しい制限値で再起動されていることを確認する。 価値観 引き継ぐ。
# 永久カーネルパラメータ
sudo bash -c 'cat >> /etc/sysctl.d/99-ulimits.conf <<EF
fs.file-max = 2097152
fs.nr_open = 2097152
EOF'
sudo sysctl -システム
#コントロール
cat /proc/sys/fs/file-max
cat /proc/sys/fs/nr_open || sysctl fs.nr_open
キャパシティ・プランニングとアーキテクチャ
現実的なキャパシティ・プランニングは、測定から始まる プロフィール リクエストあたり:ウェブサーバー、アプリレイヤー、データベース、キャッシュを合わせていくつのFDが必要か?これらの数字から、ホストごとに同時に開いているハンドルの総数を導き出し、以下のバッファを計画する。 ピーク について。ログローテーション、追加ソケット、テンポラリファイル、バックアップジョブなどの需要が増え、リソースを食い尽くします。 リザーブ. .ロードバランサーを使った水平スケーリングでは、ノードあたりのFD負荷が減少するため、障害耐性や変更ウィンドウが低下するという事実に注意を払っている。 簡易版. .階層ごとに明確な制限値を設定することで、初めて具体的な制限値を設定し、サービス間の容量を合理的に割り当てることができる。 分水嶺.
ウェブサーバーとデータベースの微調整
ウェブ・サーバーについては、私は次のルールに従う。 スレッド*4 をFD制限より小さくすることで、アップストリーム接続、一時ファイル、ログのための予備を確保している。nginxとApacheについては、keep-alive、オープンアクセス、エラーログ、アップストリームソケットを計算に入れて、安全性を確保している。 バッファ. .MariaDBやPostgreSQLのようなデータベースは、アプリケーション、レプリケーション、モニタリングに対して多くのソケットをオープンする。 フィット. .キャッシュ(Redis、Memcached)はDBの負荷を軽減するが、多くのクライアントが並行してリクエストや接続を行う場合、必ずしもFDの数を減らすことはできない。 ホールド. .そのため、フロントエンド、アップストリーム、DB、キャッシュ、メッセージキューという一連の流れに沿って制限を調整し、最初のハードリミットを超えないように計画している。 バリア に達する。.
# 例: nginx systemd のリミットとワーカー
limitNOFILE=65536 # systemd
worker_processes auto;
worker_connections 4096; # 4096 * ワーカー <= 65536
# 例: PostgreSQL
max_connections = 1000 # FD 要件 ~ 接続あたり 1-2 + ファイル/ログ
WordPressとPHPスタックを効率的に保つ
多くのプラグインを持つWordPressインスタンスは、より多くのファイル、より多くのネットワーク接続を開きます。 過去ログ. .私は、OPCacheで不要なインクルードの数を減らし、Redis Object Cacheでデータベースの負荷を減らし、CDN経由で静的アセットをアウトソースしてファイルへのアクセスを最小限に抑えています。 コネクション を使用して負荷を軽減しています。同時に、php-fpmとウェブサーバーのリミットを上げて、クーロンジョブ、クローラー、ショップのチェックアウト時のピークが問題にならないようにしています。 中断 を生成する。エラー・ログとローテーションをクリーンに処理することで、ログ・ライターが何もせずに新しいファイルを開かなくなるのを防ぐ。 かもしれない. .このように、消費削減と限界の引き上げを組み合わせることで、負荷がかかってもスタックが手頃な価格を維持できるようにしている。 スループット を保持している。.
コンテナとクラウド環境
DockerとKubernetesでは、プロセスは多くの場合、FDの制限を継承します。 ノード, そのため、最初にホスト・パラメーターをチェックし、次にサービス定義をチェックする。類似の原理がsystemd-nspawnやcontainerdにも適用されるが、実装はユニットファイル、PodSpecs、デーモンのコンフィギュレーションに オーバーライド. .私はリミットをコードとして文書化し(IaC)、新しいノードが同じリミットを持つように、プレイブックで一貫性を保っている。 バウンダリー を持ってくる。Kubernetesでは、SecurityContextsをチェックし、必要な機能を設定することで、システムサイドの 限界 が有効になります。なぜなら、スケジューリング、オートスケール、ローリングアップデートがオープンハンドルの分布を変化させ、クラスターをテストするからです。 バッファ.
# 例: コンテナホストの systemd
cat <<'EOF' | sudo tee /etc/systemd/system/myapp.service.d/limits.conf
[サービス]
LimitNOFILE=65536
EOF
# Kubernetes: podSpec (コンテナイメージはulimitを尊重する必要がある)
# 注意: rlimitの設定はランタイム/OSによって異なる必要がある
セキュリティ、レート制限、モニタリング
高い制限値は息抜きになるが、次のような攻撃対象が増える。 洪水, そのため、私はレート制限でエッジでのリクエストを制限し、ウェブサーバーで接続制限を設定している。ウェブアプリケーションファイアウォールと適切なタイムアウトによって、アイドル状態の接続がFDを恒久的にブロックすることを防いでいる。 バインド. .定期的なテストには、再現可能な負荷プロファイルを使用し、Prometheus、Netdata、Nagiosを使用して、オープンファイルやテストに関連するメトリクスを一貫して監視しています。 ソケット. .仕事量に応じて、限界値を急激に上げるのではなく、徐々に修正していく。 解体 は簡単だ。コネクション側の限界値についてもっと掘り下げたいのであれば、以下のコンパクトな記事が参考になる。 接続制限, としてネットワーク境界で使用している。 ガイド サーブする。.
EMFILEを使ったトラブルシューティング:構造化された手順
私は、まず、このようなことを考えることから始める。 ジャーナル とサービスログから、エラーの時間と頻度を絞り込む。その後、lsofを使ってプロセスごとの消費量をチェックし、リークやログの増加、異常なエラーなどのパターンを特定する。 ソケット-のタイプである。次に、設定したリミットを実際のピークと比較し、最初は一時的にリミットを上げる。 パーマネント・セッティング を導き出す。リークが見つかった場合、私はそのコンポーネントにパッチを当てるかロールバックする。 問題. .最後に、修正内容を文書化し、アラームを設定し、新たな負荷テストを計画する。 信頼 が作成する。
高いFDリミットのリソース・コストを現実的に評価する。
ファイルやソケットを開くたびにカーネル・メモリが消費される。したがって RAMフットプリント カーネルのバージョンやアーキテクチャにもよるが、1FDあたり数百バイトから数キロバイトが必要となる(VFS/ソケット構造体を含む)。何十万ものFDがあれば、これは積み重なる。私は、最悪の場合、アプリケーションに十分なページキャッシュとワーキングメモリーの空きが残るように、グローバル・ファイル・マックスの寸法を決めている。vmstat、free、file-nrによるオープンFDの傾向から、アプリケーションのために十分なページキャッシュと作業メモリを確保できるように、グローバルfile-maxを設定しています。 ピーク負荷テスト. .その目的は、ピーク負荷時にスワップに傾くことなく、過剰な再生やOOMアクティビティを誘発することのない構成である。.
配布と起動パスのトラップ(PAM、systemd、Cron)
制限が適用されるかどうかは スタートパス から。PAMベースのログイン(ssh、su、login)は/etc/security/limits.confを読み込みますが、systemdサービスは主にユニットパラメータ(LimitNOFILE)と ない 必須PAM。Cron/atは独自のコンテキストを持つことができます。そのため、サービスごとにバリデーションを行います:
- プロセスはどのように開始しますか?(systemctl status, ps -ef)
- どのリミットが本当に表示されているのか?(cat /proc//limits)
- PAMは動作しますか?(/etc/pam.d/*のPAMモジュールをチェックする)
- システム全体のデフォルトは存在するか?(systemd: system.confのDefaultLimitNOFILE)
こうすることで、アプリケーションが開始パスによって異なるFDリミットを受け取らないようにする。 一貫性のない 反応する。
計算例を用いた寸法測定の実際
に期待している。 労働者 と接続プロファイルを、必要なFD容量に逆算する:
- nginx で 8 ワーカー、各 4000 接続:~32000コネクション。原則として、nginx はアクティブな接続ごとに 1 FD を確保します。さらにアップストリーム(keep-alive)とログが ~10-20% のバッファを追加します。結果: nginxだけで~38000 FD。.
- php-fpmで150の子プロセス、子プロセスあたり通常20-40のFD(含む、ソケット、ログ):控えめに見ても6000FD。.
- Redis/DBクライアント:200並列接続、各1-2FD:~400FD。.
ホストごとの合計:~44k FD。私は リミットNOFILE nginx を 65536 に、php-fpm をアナログに、plane を 65536 に。 グローバル fs.file-maxは、すべてのサービスと予備(x1.5-x2)が収まるようにする。RAMとI/Oパスが十分であれば、ホストごとに利用頻度の高いインスタンスを数台用意し、グローバルに1~2百万FDまでスケールする。 降伏.
より深い診断:水漏れとホットスポットの発見
FDが継続的に上昇する場合は、的を絞ったツールを使って原因を探る:
# タイプ別にグループ化されたオープンハンドル
lsof -p | awk '{print $5}'.| ソート | uniq -c | ソート -nr
# 1つのプロセスのソケットのみ
lsof -Pan -p -i
# どのファイルが成長しているか(ログ、一時ファイル)
lsof +L1 # 削除されたがまだ開いているファイル
ls -l /proc//fd
# Syscallビュー: 誰が常に開いているか?
strace -f -p -e trace=open,openat,close,socket,accept,accept4 -s 0
特に危険なのは 削除されたログ, はまだ開いている:それらはスペースとFDを占有しているが、ファイルシステムにはもう現れない。再起動または明示的な再オープン(USR1経由のnginxなど)により、この問題はきれいに解決される。不適切に設定されたウォッチャー/エクスポーターは、常に新しいソケットをオープンする可能性もあります。 プール.
Inotify、epoll、EMFILEの明確な区分け
すべてのリソース制限がFD制限と呼ばれるわけではない。開発やCI環境では、Inotify(ウォッチャー制限)に関連してENOSPCでビルドが失敗することがよくある。補足として確認して設定している:
# Inotifyの制限(ユーザー全体とインスタンス)
sysctl fs.inotify.max_user_watches
sysctl fs.inotify.max_user_instances
# 増加例
sudo sysctl -w fs.inotify.max_user_watches=524288
sudo sysctl -w fs.inotify.max_user_instances=1024
epollは内部的にはFDと連動しているが、実際のボトルネックは大規模な 長寿-コネクションがFDの制限を超えることがよくある。そのため、私はepoll/イベントループのデータ(アクティブなハンドルなど)とファイルnrやプロセス関連の消費量を相関させている。.
得意な言語とランタイム(Java、Node.js、Go、Python)
ランタイムはFDを異なる方法で処理する:
- ジャワ/ネッティプロセスごとに多くのNOKチャンネルがあり、ロギングフレームワークはファイルアペンダーを開き続ける。私は寛大な制限を設定し、クローズ/リプレースの代わりに再オープン戦略でログをローテーションしている。.
- Node.jsEMFILEは、ファイルシステム負荷の高いワークロード(ウォッチャーやビルドパイプラインなど)ですぐに発生する。私は並列fsオペレーションを規制し、制限を増やし、バックオフ/リトライ戦略を設定する。.
- 御出でなさいゴルーチンによる高い並列性は、多くのソケットを開くことができる。私はダイアルとレスポンスヘッダのタイムアウトを制限し、コネクションが適切に閉じられているかどうかをチェックしている(IdleConnTimeout)。.
- Python/uWSGI/Gunicornワーカー/スレッドモデルは、ログ、ソケット、一時ファイルのためにFDを消費する。 ファイルなし-制限がある。.
これらには共通点がある:調整されたログローテーションと信頼性の高い コネクション管理 FDは徐々に上昇する。.
具体的なコンテナ:DockerとKubernetesの設定
コンテナが実際に望ましい限界を見ることができるように、私はチェーンに沿って一貫した限界を設定する:
- ドッカー・ランを-ulimit nofile=65535:65535で開始するか、デーモンのデフォルトで設定する(例:デフォルトの制限)。.
- 画像スタートスクリプトは、制限的なulimitをリセットすべきではない。.
- Kubernetesランタイム(containerd, cri-o)によって、rlimitの設定は異なってきます。私は、cat /proc/self/limits経由でポッド内でテストし、ポッド固有の設定が十分でない場合は、ノード/ランタイムのデフォルトを調整する。.
特にマルチテナント環境では、私は 総額 fs.file-maxに対抗し、個別のノードセットまたはポッドバジェットを使用してノイジーな近隣の影響を分離し、個々のデプロイメントがホストで予約されたFDを消費しないようにする。.
モニタリング・メトリクスとアラームの明確化
file-nrとfile-maxに加えて、プロセスごとのFDとトレンドラインも監視している:
- システム全体配分対最大値、変化率、ピーク/最大比。.
- プロセスごとワーカー/スレッドごとのFD、Top-Nプロセス、夜間の異常(バッチ/ジョブ)。.
- 定性的HTTPエラー率、キューの長さ、FDトレンドと同期したアクセプト/ハンドシェイクエラー。.
アラートを設定する マルチレベル70-80%で警告、設定されたリミットの90%からクリティカル、プラス 漏れ検知 7日間の上昇トレンドを通じて。こうすることで、ハードな障壁が立ちはだかる前に対応することができる。.
緊急時のランブック
EMFILEが鋭く襲ってきたとき、私は明確なステップで行動する:
- トップ・コンシューマ(lsof、/proc//fd、ジャーナル・エントリ)を特定する。.
- 一時的にソフトリミット(セッション内のulimitまたはLimitNOFILEオーバーライド)を増やし、サービスを再起動します。.
- ログが原因の場合ローテーションを停止し、再開をトリガーし、ログレベルを下げる。.
- エッジでのバーストトラフィック スロットル (料金制限/接続制限の引き上げまたは強化 - 状況に応じて)。.
- 根本的な原因の修正(リーク、積極的すぎる並列処理、タイムアウトの欠落)と恒久的な制限 締め付ける.
同じチェーンを早期に発見できるよう、文書化し、負荷テストを繰り返し、アラームを研ぐなど、フォローアップが重要である。.
簡単にまとめると
FDの制限を増やし、カーネル・パラメーターをきれいに設定し、テストされたアーキテクチャで、私は顧客にサービスを提供できる。 操縦の余地 高負荷時私はまず測定し、適切な制限値を設定し、負荷テストで検証し、レート制限、モニタリング、クリアで結果を確保する。 ルール.


