読者です 読者をやめる 読者になる 読者になる

bauer's diary

凡人の凡人による凡人のための備忘録

きたるISUCON6向け武者修行その3 -Nginxのチューニングをしてみよう-

kitakitabauer.hatenablog.com
前回MySQLのチューニングを行いました。
今回はNginxのチューニングを行います。

Nginxのバージョン確認
$ nginx -v
nginx version: nginx/1.6.1

古すぎないので問題なさそうです。

デフォルトのnginx.confを確認

/etc/nginx配下のnginx.confが読み込まれるので、そちらの内容を確認します。

$ sudo vi /etc/nginx/nginx.conf
worker_processes  1;

events {
  worker_connections  1024;
}

http {
  upstream app {
    server 127.0.0.1:8080;
  }

  server {
    location / {
      proxy_pass http://app;
    }
  }
}

尚Nginxは、conf.dディレクトリに.confを作成すると起動時に読み込むので、default.confの内容も読み込まれています。
今回は /etc/nginx/nginx.conf の方をチューニングしていきます。


worker_processes変更

ワーカープロセスの数を変更します。
応答するマシン次第ですが、Nginxは複数のプロセスの要求処理を分散させることができるので、CPUが複数コアのときも対応できるように auto にします。

worker_processes auto;


keepalive追加

バックエンドサーバと保持するコネクション数を指定します。
upstreamブロックに記述します。

upstream app {
  server 127.0.0.1:8080;
  keepalive 128;
}


MIMEタイプ定義

初期で用意されているMIMEタイプ群が定義されたファイルをincludeします。
httpブロックに記述します。

include /etc/nginx/mime.types


静的ファイルのNginxキャッシュ

デフォルトだと、スタイルシートや画像ファイルに対してもアプリケーションからHTTPアクセスしているので、Nginxからリクエストしてキャッシュするように設定します。

serverブロックにcssとimagesの設定を記述しますが、
まず各locationディレクティブの上に、rootディレクティブでドキュメントルートを設定します。

root /home/isucon/webap/public;

location /stylesheets {
  open_file_cache_max=100 inactive=20s;
  expires 1d;
}

location /images {
  open_file_cache max=100 inactive=20s;
  expires 1d;
}


expiresディレクティブ

応答のキャッシュ関連ヘッダを操作します。
クライアントに送られるExpiresとCache-Controlの値を操作します。
現在から1日がファイルの有効期限として設定されます。


open_file_cacheディレクティブ

オープンファイルについての情報を格納するキャッシュを定義します。
max=X:Xはキャッシュが格納できるエントリ数で、この数に達すると、新しいエントリのためのスペースを作るために、古いエントリは削除されていきます。
inactive=Y:Yは、キャッシュエントリを格納しておく秒数です。平たくいえば、アクセスがないキャッシュの有効期限です。デフォルト60秒でキャッシュエントリをクリアします。キャッシュエントリにアクセスがあると、タイマーはリセットされます。


最終的なnginx.conf

こんな感じになりました。

worker_processes auto;

events {
    worker_connections  1024;
    # accept_mutex_delay 100ms;
    accept_mutex off;
}

http {
  upstream app {
    server 127.0.0.1:8080;
    keepalive 128;
  }

  log_format main '$remote_addr - $remote_user [$time_local] '
                   '"$request" $status $body_bytes_sent '
                   '"$http_referer" "$http_user_agent" $request_time';
  access_log /var/log/nginx/access.log main;

  include /etc/nginx/mime.types;

  server {
    listen  80;
    server_name  localhost;

    root   /home/isucon/webapp/public;

    location /stylesheets {
      open_file_cache max=100 inactive=20s;
      expires 1d;
    }

    location /images {
      open_file_cache max=100 inactive=20s;
      expires 1d;
    }

    location / {
      proxy_http_version 1.1;
      proxy_set_header Connection "";
      proxy_pass http://app;
    }
  }
}


設定ファイルの記述ルールに違反していないかチェック

設定ファイルの記述ルール上問題ないか確認します。

$ sudo /etc/init.d/nginx configtest
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful


nginx.confリロード

これまでの変更をNginxに適用します。

$ sudo service nginx reload


nginxログのパーミッション変更

admグループに所属しないユーザが見れないので、isuconユーザでも読み取り権を与えます。

$ ll -lrt /var/log/nginx/
-rw-r----- 1 nginx adm       0 Jul 14 03:14 error.log
-rw-r----- 1 nginx adm       0 Aug 19 08:42 access.log

$ sudo chmod o+r /var/log/nginx/*

$ ll -lrt /var/log/nginx/
-rw-r--r-- 1 nginx adm       0 Jul 14 03:14 error.log
-rw-r--r-- 1 nginx adm       0 Aug 19 08:42 access.log


access.log確認

ベンチマーカーを実行するかブラウザアクセスで指定したフォーマットになっているか確認します。

$ sudo tail -f /var/log/nginx/access.log
…
10.0.2.2 - - [01/Jul/2016:11:31:58 +0000] "GET / HTTP/1.1" 200 2233 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36" 0.003
…
10.0.2.2 - - [01/Jul/2016:11:31:58 +0000] "GET /images/isucon-bank.png HTTP/1.1" 304 0 "http://localhost:3333/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36" 0.000


ベンチマークスコア確認

改めてベンチマーカーを実行します。

[isucon@localhost ~]$ ./benchmarker b
14:14:17 type:info	message:launch benchmarker
14:14:17 type:warning	message:Result not sent to server because API key is not set
14:14:17 type:info	message:init environment
14:14:20 type:info	message:run benchmark workload: 1
14:14:27 type:fail	reason:Response code should be 200, got 500	method:POST	uri:/login
14:14:29 type:fail	reason:Response code should be 200, got 500	method:POST	uri:/login
14:14:32 type:fail	reason:Expected location is miss match /, got: /mypage	method:GET	uri:/mypage
14:14:34 type:fail	reason:Response code should be 200, got 500	method:POST	uri:/login
14:14:38 type:fail	reason:Response code should be 200, got 500	method:POST	uri:/login
14:14:41 type:fail	reason:Expected html text is match: Wrong username or password, got This account is locked.	method:GET	uri:/
14:14:42 type:fail	reason:Response code should be 200, got 500	method:POST	uri:/login
14:14:47 type:fail	reason:Response code should be 200, got 500	method:POST	uri:/login
14:14:59 type:fail	reason:Response code should be 200, got 500	method:POST	uri:/login
14:15:01 type:fail	reason:Response code should be 200, got 500	method:POST	uri:/login
14:15:20 type:info	message:finish benchmark workload: 1
14:15:25 type:info	message:check banned ips and locked users report
14:15:49 type:report	count:banned ips	value:2
14:15:49 type:report	count:locked users	value:2555
14:15:49 type:fail	reason:Missmatch banned Users	message:Report checking is failed. Do not send score.
14:15:49 type:score	success:5860	fail:10	score:1266

failが出るようになった…
とりあえず、Nginxのチューニングはいったんここまでとします。


次回記事はこちら