プロセス関連のチューニング
worker_connectionsとworker_rlimit_nofile
worker_connectionsはworkerプロセスで開ける同時接続最大数です。
高スペックマシンでは要上方調整。
- worker_connections 2048;
- クライアントの最大接続数➗worker_processes数(≒ vCPU数)
- worker_limit_nofile 8192;
- 最大オープンファイル数➗worker_processes数(≒ vCPU数)
worker_connectionsはworker毎のclientの最大接続数を表しています。
defaultは512に設定されていると思います。
リバースプロキシを利用中は1アクセスでworker_connectionが2つ消費されるので通常の2倍に設定する。
- クライアント – nginx(1接続分) 通常の場合
- クライアント – nginx – プロキシ先のサーバ (2接続分) リバースプロキシの場合
worker_connectionsの値はworker_rlimit_nofileの1/2~1/4程度にします。
worker_rlimit_nofileは workerプロセスの最大オープンファイル数の上限値で、workerプロセス毎の値です。OSの上限は下記のファイルで確認できます。
# cat /proc/sys/fs/file-max
97433
workerプロセス毎の値なので上限値 ÷ worker_processの値以下に設定します
nginxの最大接続数はworker_connections × worker_processになります。
・nginxの最大接続数の計算
- worker_connection=2048
- worker_process=auto (cpu core2 )
- 2048 x 2 (cpu コア数)=4096(最大同時接続数)
- CPU使用率が低いがアクセス数が頭打ち → worker_connectionsを上げる
- CPU使用率が100% → worker_connectionsを下げて接続制限する
CPU使用率は低いのにアクセス数が頭打ちの時はworker_connectionsを高く設定します。
また逆にアクセスが多くCPU100%の場合はworker_connectionsの数を下げてアクセスを制限すると良いでしょう。
worker_cpu_affinity
各workerプロセスを任意のCPUコアにバインドすることができます。
デフォルトでは設定されておらず、workerプロセスは特定のCPUにバインドされていません。パフォーマンス向上目的で利用されることは少ない
worker_priority
workerプロセスのnice値を設定できます。nice値を低くすると優先度があがります。
デフォルトは0で、最大値は-20です。
multi_accept
multi_accept on;
default no, @events
multi_acceptはonにするとworkerプロセスが1つ以上の新しいコネクションを受け入れられるようになります。
同時接続数が非常に多いような場合はonに設定しても良い。
通常のアクセスではoffの設定で問題ない。
use epoll
epollはlinuxカーネル2.6以降で利用可能なIO多重化のシステムコール。nginxが自動で効率的なものを選択してくれるが明示的に指定も可能。
最近のLinuxではepollで良い
https://nginx.org/en/docs/events.html
キャッシュ関連の設定
キャッシュとは「一時的に保存されたコンテンツ」のことです。
クライアントのアクセス時にキャッシュを表示させるとオリジンサーバの負荷低減や表示速度を向上可能です。
キャッシュで大きな変化がみられるパターンはとしては
- キャッシュをRAM上(tmpfs)に設置
- 動的コンテンツのキャッシュ (fastCGI cache)
があります。
tmpfsで高速されるのはキャッシュが保存されている領域がSSDと比べて爆速なRAM上に設定すれば読み出しが速くなり応答が改善されるという理屈です。
nginxは静的コンテンツの他、動的コンテンツのキャッシュも可能です。
静的コンテンツと比べて、動的コンテンツはクライアントのリクエストに応じてサーバ上でコンテンツを生成するため配信側のサーバの負荷は高いです。そのため、動的コンテンツのキャッシュの効果はより高いです。
CDNは分散されたキャッシュサーバー
キャッシュサーバはクライアントとオリジンwebサーバの間に設置してオリジンwebサーバの代わりにレスポンスを返すサーバです。コンテンツを配信するのに利用するCDNは複数台に分散された可用性の高いキャッシュサーバといえます。クライアントから近い位置のCDNがオリジンサーバの代わりにキャッシュを返します。
更新頻度の高いサイトではキャッシュが新しいコンテンツに更新されずに残ってしまう場合があります。
キャッシュ更新されないとクライアントは古いコンテンツを見ることになるので注意が必要です。
そのためキャッシュを更新するための仕組み(キャッシュクリアなど)があります。
キャッシュコントロールには
- キャッシュの期限を設ける
- キャッシュするコンテンツのon offを設定する
等があります。
open_file_cache
これは通常のキャッシュとは違ってファイルのメタデータのキャッシュです。
ファイルのメタデータ(ファイルディスクリプタ、更新情報…)をキャッシュするとファイルを開く処理が短縮できます(default 無効)。実ファイルをキャッシュするわけではない。
- open_file_cache on; @server, http, location
ファイルが見つからない(404)というような状態もキャッシュしたい場合はopen_file_cache_errorsを設定します。
- open_file_cache_errors on;
キャッシュされる最大要素数はmaxで指定します。最大を超えた場合は使われていない古いものから削除されます。キャッシュの有効時間はinactiveで指定します(defaultは60s)
- open_file_cache max=1000 inactive=20s;
open_file_cacheでキャッシュされた情報はファイルがすぐに更新されるような環境ではすぐに古くなってしまうので、キャッシュを再チェックする間隔を設定します。defaultは60秒。inactiveの値よりも長くする意味はなさそう。
キャッシュするファイルの最低アクセス数を指定してinactiveで設定した時間内にその数を超えた場合にキャッシュが保持されます。1なら2以上のアクセスがあるとキャッシュが保持される?
open_file_cache_min_uses 1;
FastCGI Cache
クライアントからのリクエストに応じてphp等のプログラムを実行してhtmlページを作るページを動的ページといいます。
動的ページはプログラム実行・DBアクセスなどが入るため、サーバへの負荷が高く、レスポンスに時間がかかります。
そこで、FastCGIキャッシュを使うとプログラムで生成した静的ページ結果をキャッシュしてクライアントに返すことで大幅にレスポンス時間を早くすることが可能です。
VHの設定でキャッシュしたデータを置くパスを定義します。
fastcgi_cache_path /var/cache/nginx/cgicache levels=1:2 keys_zone=cgicache:10m max_size=512M inactive=600m;
fastcgi_cache cgicache;
fastcgi_cache_valid 200 60m;
- fastcgi_cache_path path; @http (serverセクションにかけないので注意)
- path: キャッシュデータを保存するパスを指定します。
- levels=1:2; キャッシュデータを保存する階層数と階層の文字列を指定する。数字はディレクトリの文字数を表し最高2文字。levels=1:1:1は3階層ディレクトリ1文字。性能的には2階層(1:2)がおすすめ。キャッシュファイル名はハッシュ化されている。1:2の例:/var/cache/nginx/cgicache/c/29/asijflll29c
- keys_zone=cgicache:10m; メモリに展開するキャッシュがHITかどうか判断するためのメタデータのメモリ領域名とサイズを指定。10MBで8万のキーデータ保存可能
- max_size=512M; キャッシュ総サイズの上限。max_sizeを超えたら使用頻度が低いものから削除。g(ギガバイト)も指定可
- in_active=600m; キャッシュの有効期限を設定。h, dも指定可能
- use_temp_path on|off; offでは一時ファイルをfastcgi_cache_path内に直接配置します。onまたは未指定の場合はfast_cgi_temp_pathで指定したパスに配置する
- fastcgi_cache_key キー; @http, server, location
- どの値を元に保存するキャッシュを識別するか設定する。設定したキーに対して複数のレスポンスがある場合最初に保存されたキャッシュが使用されるので注意。例:$request_uriでキー指定→GETやHEADなどリクエストメソッドによって応答が異なる場合はGET応答がキャッシュされるとHEADアクセス時にGETの結果がかえる。$request_uriにはクエリストリングは含まれないのでクエリストリングによってレスポンスが異なる場合もそれを含むようにfastcgi_cache_keyを指定する($is_args$args)。
- 例: “$scheme$request_method$host$request_uri”
- fastcgi_cache cgicache | off; default off @http, server, location
- fastcgi_cache_pathのkey_zoneで指定した値を指定してキャッシュをONにする
- fastcgi_cache_valid status code time; @http, server, location
- ステータスコードに応じてキャッシュ時間を設定できる
- fastcgi_cache_valid 200 301 302 60m; →これはfastcgi_cache_valid 60m;と同じで全ステータスコードを設定したい場合はanyを指定する
- fastcgi_cache_valid 404 1m;→個別に指定可能
- X-Accel-Expiresヘッダで優先的に設定することも可能
- fastcgi_cache_use_stale;
- fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
- fastcgiプロセスやDBがダウンした時にエラーではなくてキャッシュを返すようにする設定
- fastCGIサーバでエラーが起きた場合の処理について記述。エラーの状態によって古いキャッシュを使用するか指定可能
- error コネクション確立の失敗時
- timeout タイムアウト時
- invalid_header レスポンスヘッダが不正な時
- http_xxx レスポンスステータスがxxxの時失敗とみなす。
- updatingはキャッシュが更新されている場合にも古いキャッシュ利用を許可する
- fastcgi_cache_min_uses 1; @http, server, location
- この回数アクセスが来たらキャッシュする
- fastcgi_cache_lock on; default off @ http, server, location
- 有効にすると複数のクライアントがキャッシュではない新しいコンテンツを要求したときに一つだけがfastcgiサーバに行き、残りの要求はキャッシュを利用させるようにできる。
- fastcgi_cache_lock_timeout 5s; default 5s @http, server, location
- fastcgi_cache_lockのタイムアウトを指定。この時間を超えると要求がFastCGIサーバに渡るがキャッシュはされない。
- fastcgi_cache_lock_age 5s; default 5s @http, server, location
- 新しいキャッシュを取得するためのfastcgiサーバへの要求が指定した時間内に終わらなかった場合は他のクライアントの要求がfastcgiサーバに渡される
- add_header X-FastCGI-Cache $upstream_cache_status;
wordpressの管理画面などキャッシュされると困る部分は除外するように設定します。
$no_cache変数を定義して1の時はキャッシュすることにする。
set $no_cache 0;
if ($request_method != “GET”) {
set $no_cache 1;
}
if ($query_string != “”) {
set $no_cache 1;
}
if ($http_cookie ~ ^.*(comment_author|wordpress_[a-f0-9]+|wordpress_logged_in|wp-postpass|wordpress_no_cache).*$) {
set $no_cache 1;
}
if ($request_uri ~* “/wp-admin/|/xmlrpc.php|wp-.*.php|^/feed/*|/tag/.*/feed/*|index.php|/.*sitemap.*\.(xml|xsl)”) {
set $no_cache 1;
}
if ($remote_addr ~* “192.168.0.2|192.168.0.3|192.168.0.6”) {
set $no_cache 1;
}
キャッシュがhitせずにbypassする理由
fastcgiキャッシュを設定しているのにキャッシュがhit(キャッシュから返すステータス)せずにbypass(該当のキャッシュが使用しない)になる原因として、上記で設定したwordpress_logged_inが原因かもしれないです。
wordpress_logged_inはwordpressにログインしている時に発行されるクッキーでログイン状態だとキャッシュが使われないように設定されています。
fastcgi_cache_path /var/cache/nginx/cgicache levels=1:2 keys_zone=cgicache:10m max_size=512M inactive=600m;
server {
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include fastcgi_params;
fastcgi_cache cgicache;
fastcgi_cache_valid 200 301 302 240m;
fastcgi_cache_valid 404 403 1m;
fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
fastcgi_cache_min_uses 1;
fastcgi_cache_lock on;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_no_cache $no_cache;
fastcgi_cache_bypass $no_cache;
fastcgi_pass_header X-Accel-Expires;
add_header X-FastCGI-Cache $upstream_cache_status;
add_header no_cache_flag $no_cache;
}
proxy cacheでプロキシ先のデータをキャッシュ
nginxはキャッシュサーバとして利用することも可能です。
ブラウザにキャッシュしてもらう cache-controlヘッダ
ブラウザにもキャッシュ機能があるため複数回同じページを訪問するようなサイトではブラウザ側にキャッシュしてもらうことでwebサーバ側の負荷をへらすことができます。
Cache-Controlヘッダはリクエスト/レスポンスヘッダに付加されるヘッダでブラウザおよびキャッシュサーバのキャッシュの取り扱いについて記載されている情報です。
ブラウザからのリクエストヘッダとサーバ側からのレスポンスヘッダに記述されているcache-controlヘッダの意味合いは若干異なります。
- リクエストヘッダのcache-controlヘッダ
例えばブラウザ側がキャッシュされた情報でなくオリジンのコンテンツを取得したい場合にはCache-Control: no-cache を指定することでオリジンサーバのコンテンツ要求ができます。
- レスポンスヘッダのCache-Controlヘッダ
レスポンスヘッダはwebサーバ側が返すレスポンスにあるヘッダで間にあるキャッシュサーバやクライアントのブラウザに対して指定の期間キャッシュさせたり、キャッシュしないでほしいという要求ができます。例えばCache-Control: max-age=3600 を指定すると3600秒間そのコンテンツをキャッシュとして保存させます。
nginxの設定
- expires 7d;
- ヘッダにexpiresを追加してブラウザにキャッシュさせる日数を指定することができます。一度アクセスしてきたデータは指定の日数ブラウザ側のキャッシュに残ります。http1.0ではexpiresが優先、http/1.1ではcache-controlヘッダが優先される
- add_header 名 値; @http, server, location, if, add_header cache-control
- add_headerはcache-controlに限らずレスポンスヘッダに任意のヘッダを追加したい時に使います。
- add_header cache-control “max-age=86400”; と指定することで1日間(秒数)レスポンスをキャッシュさせることができます。 s-maxage=とすることでプライベートキャッシュ(ブラウザのキャッシュ)以外で有効な値を設定できます
- add_header cache-control “max-age=86400” always; とalwaysを指定すると4xxなどすべてのステータスコードでヘッダ追加される。
- add_header cache-control “no-store, private”; というように複数の値を設定可能
- no-cache 紛らわしいがキャッシュをしないという指示ではなくキャッシュを使用するかオリジンに聞いてから利用してという意味。キャッシュ自体は行われる。(do not use cache until revalidate)
- no-store キャッシュはさせないようにするにはこちらを入れる。これは暗黙的にmax-age=0も含む。must-revalidateはキャッシュがある時のみ有効になり、再検証が行われるため指定の意味なし。(do not cache)
- private プライベートキャッシュ(ブラウザ)のみOK。共有キャッシュ(CDNとか)はだめ
- public キャッシュOK
- must-revalidate キャッシュの有効期限が切れるとオリジンに再検証が行われますが、must-revalidateがあるとキャッシュを使用する前に毎回検証が行われます。max-ageやexpiresが無い場合はLast-Modifiedヘッダーから最終更新日を取得して、現時刻の差をとってその10%を有効期限に設定することが多い(最終更新が長いほど有効期間が長くなる300日なら30日)。有効期限切れのキャッシュはstale状態になりオリジンへの検証・再取得が発生するがクライアントが期限以上のmax-staleの値を設定しているとstaleのキャッシュを受け入れる。must-revalidateがある場合はstaleのキャッシュ利用を許可しない。プライベートキャッシュは有効にしたい場合はproxy-revalidateを使用します。
通信関連のパフォーマンス設定
ブラウザにHTTPSで接続してもらうようにする
最近はセキュリティ上の問題で暗号化されていないhttpでの接続を許可しないでhttpsのみを公開とすることが世の流れになっていますがURLの記述がhttpのままの場合などブラウザがhttpでアクセスしてくることもあるので大抵はhttp→httpsにリダイレクト設定していると思います。
このhttpでのアクセスもwebサーバにアクセスが来ているのでわずかに負担になります。
そこでブラウザ側に「このサイトはhttpsで接続する」というように覚えさせたり強制させるHSTS(Hypertext Strict Transport Secrutiy)という仕組みがあります。
この設定はnginx側でヘッダーを追加することで簡単に実装できます。
ヘッダーに追加する場合は次回からの接続はHTTPSに接続してくるようになるので一回目の接続はhttpで接続が来てしまいます。
これも回避したいという場合はhttps://hstspreload.org/ のプリロードリストに登録すれば一回目からもhttpで接続するようになります。
- add_header Strict-Transport-Security ‘max-age=31536000; includeSubDomains; preload’ always;
- maz-ageは2年間設定することが多い。preloadに設定するとプリロードリストを参照, alwaysを付けるとエラーレスポンスなど全てのレスポンスに対してヘッダーを付加するようになる
データの圧縮
webサーバが返すデータが大きいほどwebサーバの応答が遅くなる原因になります。
- ネットワーク帯域を圧迫
- ディスクI/O負荷が上昇(ディスクからデータの読み出し)
nginxには配信データをgzipで圧縮する機能があります。サーバは圧縮、クライアントは解凍のためにCPUを使用しますが、転送データサイズを小さくすることのほうが重要です。
転送データサイズを小さくする戦略として
- コンテンツサイズを小さくする
- 特に画像や動画はgzip圧縮しにくいので解像度を下げたり高圧縮コーデックで変換する
- nginxのgzip圧縮機能を有効化する
- 圧縮率を高くしすぎるとサーバのCPU負荷が上昇する
- gzip_staticで予め圧縮したファイルを配信する – 最も高速だが圧縮ファイルを準備する必要がある
データ圧縮のデメリット
基本的には圧縮のメリットが大きいですが、デメリットもあります。
- 圧縮効率の悪いファイル(動画や画像、音声)は負荷が無駄にかかるだけでメリットがない
- 高圧縮にすると負荷上昇に対して圧縮率が低い
- BREACH攻撃の対象になる(ページにユーザ固有の秘密情報が表示されていなければ問題にならない)
- 対応していないブラウザでは使えない(有名どころは対応しているので無視して良い)
BREACH攻撃は圧縮前後のファイルサイズ変化を比較して暗号を解読してコンテンツに含まれる機密情報を解読する手法です。同じ圧縮アルゴリズムを使っていれば秘密文と同じ文章が入ったものを用意して圧縮すれば同じファイルサイズになるため秘密文を推測することができます。
攻撃者はデータサイズがわかればよく中身を見る必要はありません。Webサーバからのレスポンスに秘密情報を含む場合はHTTPSでgzip圧縮の利用は推奨されていません。
BREACH攻撃への対策は
- 秘密文を固定化しない
- 同一IPやUAからの繰り返しのアクセスを制限する(解析のために複数回のアクセスが必要なため)
- 毎回ランダムなデータを挿入する(ハッシュ化のソルトと同じ)
などがあります。
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Accept-Encoding
ngx_http_gzip_moduleで動きます。(デフォルトで有効)
gzip_staticを利用するにはngx_http_gzip_static_moduleが必要です。
- gzip onまたはoff;
- http, server, location, if内に記述可能です。デフォルトはoffです。
- gzipに対応していないブラウザはほぼないので有効化しても問題ない
- gzip_comp_level 1~9; 9が最も高圧縮だが負荷が高い defaultは1 たいてい1,2で良いが圧縮レベルを求めるなら4~6くらいがちょうど良さそう。log_formatで$gzip_ratioを設定すると圧縮比がログで確認できる
- gzip_static onまたはoffまたはalways;
- http, server, locationに設定可能。デフォルトはoff
- onにすると予め圧縮したファイルがある場合それを配信する。offにするとリクエストの都度圧縮するので負荷がかかる。 alwaysにすると常に圧縮ファイルを返すようになる。
- gunzip on または off; gzip_static always; を設定した際にブラウザが圧縮に対応していない場合は圧縮ファイルを解凍してブラウザに返す
- gzip_min_length 20; 圧縮する最小のバイト数。小さいファイルの圧縮はむしろファイルサイズが増加することもあるので設定を入れる。1000byteとか。ここのbyte数は実ファイル容量ではなくContent-Lengthヘッダーをみて決定するのでこのヘッダが空の場合gzip_min_lengthで設定した容量未満のファイルでも圧縮がかかってしまう。
- gzip_types (mime-type); defaultはtext/html。http, server, locationに記述できる。画像系は除外してテキスト系を入れる。text/css text/xml text/plain application/json application/javascript
- gzip_disable “msie6”; gzipを無効化するuseragent(UA)を指定。非対応はmsie6くらい
- gzip_vary on | off ; (default off) @ http, server, location
- nginxの前段にキャッシュサーバやCDNがある場合はonにする。
- onにするとnginxはVary : Accect-Encodingヘッダを付加する。前段のサーバはクライアントのAccept-Encodingを読んでレスポンスを返すようになる。
- gzip_http_version 1.0 | 1.1; (default 1.0) @http, server, location
- gzipを有効にする最低のHTTPバージョンを指定。1.0なら1.1でも有効
- nginxの前段のLBやCDNが付加するviaヘッダがあるとgzip_varyを有効化にしてもnginxは圧縮しないが、gzip_proxied any;を設定すると圧縮する
- off プロキシされたリクエストは全て圧縮無効
- レスポンスヘッダCache-Controlヘッダをみて指定があれば圧縮を有効にする (expired, no-cache, no-store, private, authorization…)
- zgip_proxyの設定はプロキシされた前提(前段にキャッシュサーバがある)なのでキャッシュされるコンテンツは圧縮しないで、キャッシュされないものは圧縮しようという発想。キャッシュされているかどうかはCache-Controlヘッダをみるとわかるno-cacheなどの値があればキャッシュされないので指定すると圧縮する。cache-controlヘッダはキャッシュサーバだけでなくクライアントのブラウザ側のキャッシュ動作にも影響する
# nginx -V 2>&1 | tr ' ' '\n'|egrep _module | sed -e 's/--with-//g'
http_addition_module
http_auth_request_module
http_dav_module
http_flv_module
http_gunzip_module
http_gzip_static_module
http_mp4_module
http_random_index_module
http_realip_module
http_secure_link_module
http_slice_module
http_ssl_module
http_stub_status_module
http_sub_module
http_v2_module
mail_ssl_module
stream_realip_module
stream_ssl_module
stream_ssl_preread_module
帯域の調整
一部のクライアントに帯域を占有されると他のクライアントの通信を妨げる原因になるため、帯域の上限を設定して一部の帯域占有を防ぐことができます。通常同一のクライアントからの接続要求はそこまで大きくないため、異常に多い同時接続数や転送量は攻撃の可能性があります。帯域制限はセキュリティ対策(DDos攻撃やBREACH攻撃、ブルートフォース攻撃対策等)に有効です。
転送レート制限
- limit_rate 100k; default 0; (0は制限なし)@ http, server, location, if
- 最大転送量レートを100kb/sにする。これは1つのリクエスト毎の値。クライアントが同時接続数をいくらでも増やせると意味がないため、同時接続数の制限も行うべき。
- limit_rate_after 500k;default 0, @ http, server, location, if
- 500kbまでは制限なし、500kbを超えたらlimit_rateで設定した転送レート制限を適用するように設定できる
リクエストレート制限
- limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; @http
- 接続数の制限に必要なlimit_conn_zoneを指定。keyとする変数名を指定($binary_remote_addr等)、zone=ゾーン名:ゾーンの最大容量、rate=リクエスト数 r/s(秒) or m(分)で設定
- 設定されたキーをもとにoneという10MB領域のゾーンにリクエスト情報(セッション情報)が保存される。ここのzoneでは秒間1リクエストを超えた処理はできず、503を返す。1MB当たり16万のリクエスト情報を保存できる。10MBを超えると使用頻度の低いものから消去される。
- limit_req zone=one burst=5; @ http, server, location
- limit_reqではlimit_req_zoneで設定したレート制限を超えた場合に何リクエストまでは503を返さず(limit_req_statusの値)に保留、遅延処理させるかを設定できる。遅延させない場合はnodelayを設定する。
- limit_req_status 503; @http, server, location
- 制限を超えた時に返すエラーコードを設定。初期は503
コネクション制限
- limit_conn_zone $binary_remote_addr zone=addr:10m; @http
- limit_req_zoneと同じ
- limit_conn addr 1;@ http, server, location
- 指定したキーに対して許可する最大接続数を設定する。
- limit_conn_zone $server_name zone=perserver:10m; のように$server_nameを指定することでVHごとの総接続数も制限可能。
カーネル・その他の設定
sendfile
sendfileはカーネルの機能であるsendfileシステムコールを利用するオプションです。通常はリクエストの処理でファイルの読み出し、カーネルキャッシュ、プロセスバッファーを経てネットワークにsendする所をsendfileシステムコールを利用するとカーネルバッファからプロセスを経ずにネットワークにsendすることができるのでパフォーマンスが向上します。ただし、https通信では使えないようです。
- sendfile on | off; default off,
- 場所:http, server, location, if
環境によってはsendfileがonになっていることでバグが起こることがあるのでその場合offにしたほうがよいです。例:古いカーネル、仮想環境、NFS利用、tmpfs
tcp_nopush
tcp_nopush on | off; はsendfileがonの場合のみに有効なオプションでonにするとレスポンスヘッダーとパケットの先頭を一つのパケットとして送信するためパフォーマンスが向上します。
非同期処理・thread pool
イベント駆動型のnginxの処理は特定の重い処理が発生した場合その処理が終了するまで他の処理が進行しないブロッキングが発生し、後続の処理待ちを発生させてパフォーマンス低下します。ディスクからのファイル読み込みはブロッキングを発生させる処理の代表例ですが、nginxではaioディレクティブを適用することで非同期I/Oを利用できます。スレッドプールの利用も有効です。スレッドプールは大容量ファイルの配信(I/O負荷が高いもの)やRAMが小さい場合に有効です
- :aio on | off; @http, server, location
- aio threads;
- directio 256k; direct I/Oを使用しない最小容量を指定。ダイレクトI/Oは小さい大きいファイルの場合に有効で小さいファイルに対しては逆効果になる。カーネルキャッシュを介さずに直接プロセスキャッシュに読み込む。