Help us understand the problem. What is going on with this article?

nginxの基本設定を改めてちゃんと調べてみた

More than 1 year has passed since last update.

本記事はLIFULL Advent Calendar 2017 - Qiitaの17日目の記事です。

nginxの設定を触る機会があり、改めてnginx.confについて調べてみました。
私自身勘違いしていた箇所や、わかっていなかった箇所があり新たな気づきになりました。
※まだ勘違いしているところがあればコメントいただけると嬉しいです。

nginx.confの構造

nginx.confは以下の様な構造で記述されています。
ファイル自体は/etc/nginx/nginx.conf/にあるかと思います。

nginx.confは通常以下の様な形式で書かれています。

/etc/nginx/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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした