本記事はLIFULL Advent Calendar 2017 - Qiitaの17日目の記事です。
nginxの設定を触る機会があり、改めてnginx.confについて調べてみました。
私自身勘違いしていた箇所や、わかっていなかった箇所があり新たな気づきになりました。
※まだ勘違いしているところがあればコメントいただけると嬉しいです。
nginx.confの構造
nginx.confは以下の様な構造で記述されています。
ファイル自体は/etc/nginx/nginx.conf/
にあるかと思います。
nginx.confは通常以下の様な形式で書かれています。
# 基本ディレクティブ
設定A 設定値1;
設定B 設定値2;
# ブロックディレクティブ
events {
設定C 設定値3;
:
}
http {
server {
設定D 設定値4;
location 設定値5 {
設定E 設定値6;
}
}
server {
設定E 設定値6;
}
設定のことを「ディレクティブ」と呼びます。
設定A 設定値1;
がディレクティブです。
また、events { 設定C 設定値3; }
という形式で書かれたものは「ブロックディレクティブ」と呼びます。
また、ディレクティブは設定ファイル内のどこにでも記述できるものではなく、ディレクティブ毎に決められたコンテキスト内に記述する必要があります。
つまりブロックディレクティブ内か外か、どのブロックディレクティブ内に記載するかが決まっているという事です。
mainコンテキスト
ブロックディレクティブの外に記述する基本ディレクティブについて記載していきます。
user
nginxを起動したときのmaster process以外を起動するユーザを設定できます。
master processはrootユーザーで起動します。
user nginx;
で設定して起動すると以下の様にworker processがnginxで起動している事がわかります。
$ ps aux |grep nginx |grep -v grep
root 1006 0.0 0.1 59144 1048 ? Ss Dec11 0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx 1008 0.0 0.3 59592 3792 ? S Dec11 0:00 nginx: worker process
worker_processes
worker_processesはnginxのworkerプロセス数を設定します。
通常はCPUのコア数以下に設定します。イベント駆動のアーキテクチャのため、CPUのコア数より多い数のプロセスを動作させても意味がありません。
今回はEC2のt2.microを使用しているのででコア数は1です。そのため、1を設定するので問題ありません。
また、autoの設定もあります。autoだとコア数を見て自動で設定してくれるようです。
↓ auto設定の時のworker
$ ps aux |grep nginx |grep -v grep
root 1006 0.0 0.1 59144 1048 ? Ss Dec11 0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx 1008 0.0 0.3 59592 3792 ? S Dec11 0:00 nginx: worker process
worker processは1になっています。
worker_rlimit_nofile
ファイルディスクリプタの設定になります。ここを設定する事でworkerプロセスが最大に開けるファイル数の制限ができます。
ulimit -n
以上のファイル数を処理できるようになり、「too many open files」問題を回避できます。
$ ulimit -n
1024
まずはファイルディスクリプタとは何かから。
ファイルディスクリプタはプログラムがアクセスするファイルや標準入出力などをOSが識別するために用いる識別子です。
0~2まではOSは予約済みとなっています。
識別番号 | 説明 |
---|---|
0 | 標準入力(stdin) |
1 | 標準出力(stdout) |
2 | 標準エラー出力(stderr) |
3~ | ファイルオープンした際に順にディスクリプタが割り当てられる |
シェルを書く時によく使うcommand > /dev/null 2>&1
の数字部分がファイルディスクリプタに当たります。
上記のコマンドを左から説明をすると
コマンド | 説明 |
---|---|
command | 任意のコマンド。 |
> | 標準出力のリダイレクト |
/dev/null | Unix系におけるスペシャルファイルの1つ。書き込み内容を全て破棄する |
>& | >&{ファイルディスクリプタ}は結果をマージする |
つまり「{command}の標準出力(1)を標準エラー出力(2)にマージして内容を捨てる」ということです。
(場合にもよりますが、何か問題が起きた時に検知できないのでとりあえずで結果を捨てるのはよよろしくないです)
$ hoge
-bash: hoge: コマンドが見つかりません
$ hoge > /dev/null 2>&1 # 何も出力なし。
上記の様にエラーメッセージも何も出力されなくなります。
次にファイルディスクリプタ:3以降がどうなるかです。以下を見るとすぐわかると思います。
file = File.open('/tmp/hoge', 'r')
puts file.fileno # ファイルディスクリプタ ⇒ 3
file.close
file = File.open('/tmp/fuga', 'r')
puts file.fileno # ファイルディスクリプタ ⇒ 3 file.closeをするとファイルディスクリプタは再利用される。
file = File.open('/tmp/fuga', 'r')
puts file.fileno # ファイルディスクリプタ ⇒ 4
この様にファイルオープンする度に連番で割り振られていきます。
ファイルディスクリプタは連番で採用されていきますが上限があります。
上限はulimitで確認できます。
$ ulimit -n
1024
ここでworker_connectionsを1024以上に設定する場合は、上限を変更する必要が出てきます。
というのも同時接続数がファイルの上限を超えてしまうため、「too many open files」となってしまうためです。そのため、worker_connectionsもしくはファイルディスクリプタ(worker_rlimit_nofile)を変更する必要があります。
ファイルディスクリプタを変更するときはOS全体で扱えるファイル数を超えないように注意が必要です。確認方法は以下になります。
$ cat /proc/sys/fs/file-max
99560
error_log
そのままerror logの出力場所になります。
この設定はhttpやserverブロックなどでも使用することができます。
pid
PIDを格納するファイルの出力場所の指定になります。
ps
コマンドで確認してしまうのであまり見る事は無い様に思います。
eventコンテキスト
イベント処理に関するモジュールについての設定項目になります。
worker_connections
「nginx」全体の接続数です。
私は勘違いしていたのですが「同時接続数 = worker_processes * worker_connections」ではない様です。
worker_rlimit_nofileでも記載しましたがworker_connectionsはファイルディスクリプタ値以上を設定することが出来ないので、必要に応じて変更する必要があります。
multi_accept
multi_accept on;
にする事でリクエストを同時に受け付けられる様になります。
onにするかはマシンスペックなどとのご相談になると思います。
use epoll
コネクションの処理方法を記述します。
Linuxカーネル2.6以上の場合はepoll、BSDの場合kqueueとするのが良い様です。
特に指定しなかった場合は自動で選択される様です。
accept_mutex
onにするとworkerプロセスは順番に新しい接続を受け入れるようになります。
新しい接続の量が少ない場合はworkerプロセスの一部がシステムリソースを無駄にすることになります。
デフォルトではoffとなっています。
httpコンテキスト
httpに関するモジュールについての設定項目になります。
server_tokens
エラー画面の時に Nginxのバージョンを表示するかどうかの設定です。
セキュリティ上、バージョンを表示することは好ましく無いのでoffとしておいた方がいいです。
include /etc/nginx/mime.types;
MIMEタイプと拡張子の関連付けを定義したファイルの読み込みです。
MIMEタイプとは「タイプ名/サブタイプ名」で定義されたデータ形式の指定です
WEBサーバとブラウザはこのMIMEタイプを用いてデータの形式を指定しています。
以下のように定義されています。
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/javascript js;
...
}
default_type
mime.typesで拡張子からMIMEタイプを決定できなかった際に、ここで指定したMIMEタイプが適応されます。デフォルトはtext/plainとなっています。
access_log
access logの出力先です。
log_format
を使用する事でフォーマットを指定することができます。
またserverコンテキスト内に記載することもできます。
sendfile
onにする事でカーネルのsendfileを使用します。
ハードディスクio処理とsocket-io処理のバランスを取るため、有効にするのが良さそうです。
デフォルトはoffになっています。
tcp_nopush
onにする事でレスポンスヘッダとファイルの内容をまとめて送るようになり、少ないパケット数で効率良く送ることができます。
tcp_nodelay
通常TCPパケット・セグメントの容量いっぱいにデータを格納しようとするため、パケットの送信までにはどうしても待ち時間が発生してしまいます。
onにする事でこの待ち時間を無くすことができ、結果パケット数と送信量を増やすことができます。
keepalive_timeout
HTTPの接続時間です。
古い記事になってしまうが設定次第でプロキシサーバとバックエンドサーバ、双方の負荷軽減に効果がありそう
NginxでリバースプロキシをKeepAliveしたときの性能検証 - Qiita
Nginx の keep-alive の設定と検証 - How old are you?
gzip
onにすることでレスポンスにgzipを使用するようにでき、サーバー間の転送量を抑えることができます。
gzip_types
でgzipを有効にするファイル形式を指定し、gzip_proxied
で指定しているリクエストタイプに対してのみ有効になります。
またgzip_min_length
を指定すると設定値以下の容量の時は圧縮しないようにできます。小さいサイズの時は圧縮にかかるコストの方が高くなってしまうためです。
nginxの前段にキャッシュサーバやCDNが配置されている際はgzip_vary
を設定する必要があります。
コンテンツキャッシュとVaryヘッダとnginx - Qiita
gunzip
onにするとgzipに対応していないブラウザに対しての処理を有効にできます。
gzip_disable
でgzipに対応していないブラウザの時圧縮を無効化することもできます。
serverコンテキスト
serverに関する設定項目になります。
vhostの設定などを行ったりします。
設定項目は基本的にhttpと同じになります。
listen
どのポートで受けるかを定義します。
nginxをそのまま使う場合はhttpブロック内に記載しますが、通常はvhostで使用すると思うのでserverブロック内に記載することになると思います。
server_name
指定したhostでのリクエストの時、設定を適応させるかを設定します。
location
ごとに別のサーバを指定することも可能です。
処理の流れは以下を参照いただくといいと思います。
nginxがリクエストをどのように処理するか
root
このserverブロック内で使用するルートディレクトリの指定です。
try_files
スペース区切りでファイルを記述すると順番にファイルにアクセスしていきます。
rewrite
リダイレクトをさせたい時に設定します。
正規表現による指定も可能です。
locationコンテキスト
指定したlocationの場合に設定を適応させることができます。
このpathへのアクセスの場合はこのlocationブロック内の設定を適応させると言うことができます。
記述方法はこちら
5.2 locationの例
まとめ
最初にも書いたのですが、私自身勘違いしていた箇所や、わかっていなかった箇所があり新たな気づきになりました。
正しく設定されていないとパフォーマンスへの影響やセキュリティ上よくないことにもなるので理解の上、設定していきたいですね。
ここに記載していない設定項目もまだありますが、その項目を設定する機会があれば書き足していこうと思います。
参考)
Nginxのパフォーマンスを極限にするための考察
ファイルディスクリプタについて理解する
nginx最大パフォーマンスを出すための基本設定
メモ: nginxのAccess-Control-Allow-Origin設定 - Qiita