Nginx - ファイルディスクリプタ設定(Too many open files 対策)!

Updated:


Linux では、1プロセスが同時オープン可能なファイルディスクリプタの上限に達すると “Too many open files” などというエラーを発生します。
OS 上でのファイルディスクリプタ設定についての記事は結構存在するので、対策はそれほど難しくありません。
しかし、Web サーバ Nginx が絡むと若干ワナにかかる可能性があります。

以下、その事象、対策についての記録です。
不勉強なので、それほど突っ込んだ内容ではありません。当方が行なった対策についての記録です。

0. 前提条件

  • CentOS 6.5 上での作業を想定。
  • Web サーバは Nginx 1.4.7 を想定。
  • Web アプリ・サイトは Ruby on Rails で構築されていることを想定。(当方の場合)

1. 発生事象・原因

突如、自前で運用中の Web サーバにアクセスると、ブラウザ上に以下のようなメッセージが表示されるようになった。

500 Internal Server Error
If you are the administrator of this website, then please read this web application's \
log file and/or the web server's log file to find out what went wrong.

そして、 Ruby on Rails のログには以下のようなメッセージが出力されていた。(一部伏せ字)

File: production.log

1
2
3
4
F, [2014-04-04T17:16:57.934648 #15986] FATAL -- :
Errno::EMFILE (Too many open files - /usr/bin/xxxxxx):
  app/controllers/json_blog_controller.rb:9999:in `xxxxxxxxxx'
  app/controllers/json_blog_controller.rb:99:in `xxxxx'
  • EMFILE … 「プロセスが使用中のファイル・ディスクリプタが多すぎる」という意味。

このエラーからも分かるように「プロセスが使用中のファイル・ディスクリプタが多すぎる」ことが原因のようだ。

2. 対策(Nginx 上)

2-1. 現状確認

以下のようにして、現状の上限設定を確認する。

# ps ax | grep nginx | grep worker
 9846 ?        S      0:00 nginx: worker process

# cat /proc/9846/limits | grep 'open files'
Limit                     Soft Limit           Hard Limit           Units
Max cpu time              unlimited            unlimited            seconds
Max file size             unlimited            unlimited            bytes
Max data size             unlimited            unlimited            bytes
Max stack size            10485760             unlimited            bytes
Max core file size        0                    unlimited            bytes
Max resident set          unlimited            unlimited            bytes
Max processes             7868                 7868                 processes
Max open files            1024                 4096                 files
Max locked memory         65536                65536                bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       7868                 7868                 signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us

Max open files の「ソフト上限値」がデフォルトの 1024 となっている。

2-2. Nginx 設定

Nginx の設定ファイルを以下のように編集する。(必要部分のみ抜粋)

  • プロセス毎のファイルディスクリプタ上限数を指定する設定項目 worker_rlimit_nofile という項目を追加する。
  • worker_rlimit_nofile の設定値は worker_connections の値の3〜4倍程度がよいらしい。

File: /usr/local/nginx/conf/nginx.conf

1
2
3
4
5
worker_rlimit_nofile  4096;  # <= worker_connections の 3 - 4 倍程度

events {
      worker_connections  1024;
}

設定変更後、Nginx を再起動する。(nginx -t で構文チェックしてからでもよい)

# /etc/init.d/nginx restart
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
nginx を停止中:                                            [  OK  ]
nginx を起動中:                                            [  OK  ]

2-3. 再確認

以下のようにして、設定後の状況を確認する。

# ps ax | grep nginx | grep worker
11130 ?        S      0:00 nginx: worker process

# cat /proc/11130/limits | grep 'open files'
Limit                     Soft Limit           Hard Limit           Units
Max cpu time              unlimited            unlimited            seconds
Max file size             unlimited            unlimited            bytes
Max data size             unlimited            unlimited            bytes
Max stack size            10485760             unlimited            bytes
Max core file size        0                    unlimited            bytes
Max resident set          unlimited            unlimited            bytes
Max processes             7868                 7868                 processes
Max open files            4096                 4096                 files
Max locked memory         65536                65536                bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       7868                 7868                 signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us

Max open files の「ソフト上限値」が設定したとおりになった。

3. 対策(OS 上)

Nginx の各プロセスの上限値の設定は上記のとおりだが、OS にもファイルディスクリプタの上限を設定する。

3-1. 現状確認

以下のようにして現状を確認する。(”/proc/sys/fs” ディレクトリ配下にファイルシステム関連の設定ファイルがある)

# cat /proc/sys/fs/file-nr
3264    0       100324

左から、「オープンされているファイル数」、「空きファイル管理データの数」、「システム中のオープンファイル管理データの最大数(file-maxと同じ)」となっている。

「システム中のオープンファイル管理データの最大数」は以下でも確認できる。

# cat /proc/sys/fs/file-max
100324

3-2. 設定変更

「システム中のオープンファイル管理データの最大数」を以下のようにして設定する。(現状の倍程度にしてみた)

# echo 200000 > /proc/sys/fs/file-max
# cat /proc/sys/fs/file-max
200000

3-3. 恒常的な設定

前述の方法では、マシンを再起動した際に設定が元に戻ってしまうので、以下のようにする。

File: /etc/sysctl.conf

1
fs.file-max=200000  # <= 追加
# sysctl -p

3-4. システムユーザ毎の設定

上記の方法は OS 全体に対しての設定であったが、システムユーザ単位にも設定しておく。

File: /etc/security/limits.conf

1
2
* soft nofile 4096
* hard nofile 4096
  • * は全ユーザという意味。(ユーザ名を個別に指定することも可)
  • soft の値を超えると警告が出る。
  • hard の値を超えることはできない。
  • soft の値は hard 以下にする必要がある。
# sysctl -p

4. 注意

  • ulimit コマンドは一時的に設定を変更するもの。
    各サービスの起動スクリプト内に記述するなどして使用する。
  • “/etc/security/limits.conf” は PAM 認証後に有効になる設定。
    PAM 認証を介さないものは、この設定に意味はない。
  • ulimit コマンドや limits.conf で設定した値は、 Nginx の worker_rlimit_nofile で上書きされる。

5. 参考サイト


詳細に突っ込んだ調査はしていませんが、ファイルディスクリプタの上限値設定には色々とワナが潜んでいるようです。
ワナが潜んでいるということを知っておくだけでも、有事の際の不具合特定の高速化に役立つでしょう。

以上。





 

Sponsored Link

 

Comments