あっかぎのページ

nginxでWebサーバー(さくらVPSへお引越2)

20151207_1

ロリポップからさくらVPSへ引越ししたお話2として、今回はnginxでWebサーバー編です。

nginxでWebサーバー

このサイトをさくらVPSへ引越しするにあたって、Webサーバーが必要になりました。

ロリポップではレンタルサーバー側でApacheがWebサーバーとして動いていました。ところが、VPSではWebサーバー自体も自分で準備する必要があります。今回は勉強も兼ねて『nginx』というWebサーバーを使うことにしました。この『あっかぎのページ』もnginx上で動いています。nginxについては、このあたりの記事が参考になると思います。

サーバーの簡単なチェックツールとしては、次の物を使ってみました(記事の最後に簡単におまけ2 Webサイトのベンチマークでご紹介)。

実はApacheも試してみた結果、このサイトの規模(1000PV/日)くらいならnginxでもApacheでもそれほど性能に差は見られませんでした。

さくらVPSの1Gプランですが、どちらも秒間10リクエストくらいは数値が出ていますので、おそらく10,000PV/日くらいの規模までならApacheでもnginxでもどっちでもいい気がします。そして、10万PV/日以上のサイト運営者なら、ぼくのお引越し記事などは読む必要はなさそうですね(^^;

ということで、以下はnginxでWordPressを簡単に立ち上げるところまでを扱いますが、あくまで勉強やお試し程度の内容になります。注意:WordPressそのもののインストールは取り扱いません。

手順

記事の内容では、nginxをインストールしてWordPressを立ち上げるまでを紹介します。ついでに、1サーバー上で複数のサイトを使うバーチャルホストについても書いておきます。

  1. nginxのインストール
  2. php-fpmの導入
  3. nginxのWordPress用の設定
  4. nginxでバーチャルホスト

nginxのインストール

今回はDebianにインストールしますが、他のOSについてもパッケージが準備されていたり、簡単な手順でインストールできるようになっています。

上はnginxの公式サイトのインストール説明ページです。テキストベースの昔っぽい作りでとてもシンプルですね。

Debianの最新安定板のJessie(stable)のnginxは1.6.2-5と少し古いバージョンになっているので、nginxの公式インストールにしたがって新しいnginxを使うようにします。

まずは、nginxパッケージのセキュリティチェックとしてnginxの署名を登録します。

$ wget http://nginx.org/keys/nginx_signing.key
$ sudo apt-key add nginx_signing.key

次に、nginxの公式パッケージリストを自分のDebianのsources.listに追加します。

$ sudo vi /etc/apt/sources.list

...
deb http://nginx.org/packages/mainline/debian/ jessie nginx
deb-src http://nginx.org/packages/mainline/debian/ jessie nginx

sources.listを追記したので、更新をかけてからnginxをインストールします。

$ sudo apt-get update
$ sudo apt-get install nginx

これでnginxがインストールされます。インストール確認は次のようにします。

$ sudo nginx -v
nginx version: nginx/1.8.0

2015年12月時点ではバージョンの1.8.0がインストールされました。

最後にサーバーを起動してみて、きちんと動作するか確認します。

$ sudo service nginx start

ブラウザーでサーバーのIPアドレスにアクセスすると下のような『Welcome to nginx!』が表示されれば正常にWebサーバーが起動しました。(もし、この時にApacheが起動していたらポートが競合してしまいますので、Apacheは停止しておきます $ sudo service apache2 stop)

20151207_1

php-fpmの導入

WordPressを動作させるにはPHPが必要になります。nginx単体ではPHPの動作ができませんので、php-fpm(PHP FastCGI Process Manager)というPHPドライバーを導入してWebサーバー上でPHPが動作するようにします。

まずは、php-fpmをインストールします。

$ sudo apt-get install php-fpm

続けてphp-fpmの設定です。

$ sudo vi /etc/php5/fpm/pool.d/www.conf

ぼくの場合はwww.confの中身ので次の部分をチェックしています。

user = www-data
group = www-data
listen = /var/run/php5-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660 # コメントを外す

userやgroupをApacheなどと同じwww-dataにしています(php5-fpmのデフォルトのまま)。また、listenにはphp-fpmが受け取る方法を指定します。ここでは、unixソケットを利用してデータ待ち受けすることにします(同一サーバー上ならTCPポート指定よりもunixソケットの方が高速)。

ここで、上記の所有権の設定を間違えるとnginxからのデータを受け取れずにエラーが出たりPHPが動作しませんので、所有者や実行権限をチェックしておきます。

実際にphp-fpmを起動して、実行権限も確認します。

$ sudo service php-fpm start
$ ls -l /var/run/
-rw-r--r--  1 root        root           5 Nov 26 22:44 php5-fpm.pid
srw-rw----  1 www-data    www-data       0 Nov 26 22:44 php5-fpm.sock

上のような感じで、設定した場所にphp-fpmのpidファイルとsockファイルが表示されると思います。この時、php5-fpm.sockのファイル所有者と権限が問題ないかも見ておきます。(TCPポートで設定した場合は$ netstat -aで設定したポートで待ち受けているかをチェック)

よくあるエラーやPHPの起動しない理由がこのphp5-fpm.sockの所有権と権限です。nginxの起動したプロセス所有者・グループ権限がphp-fpm.sockと違うために動かない場合です。

上の例では、php5-fpm.sockの所有者(www-data)かグループ(www-data)しか読み書き権限がないので、nginxの起動者・グループが上のどちらかに当てはまらないとWeb上でPHPプログラムの受け渡しができなくなります。

nginxの所有権はnginx.confで設定できますので、もしPHPが動作しない場合は上の権限を1度チェックしてみましょう。簡単な確認方法としては、先ほどのphp-fpmの設定ファイルで

$ sudo vi /etc/php5/fpm/pool.d/www.conf
...
listen.mode = 0666

上のようにphpの待ち受けunixソケットの読み書き権限を全員に許可します。これでPHPが動作した場合はnginxかphp-fpmどちらかの所有権の設定に問題があることがわかります。

その他に動作しない場合は、unixソケットのファイル場所の指定間違いやnginx側の設定ミス(nginxのデフォルトはnginxが所有者・グループなので特に注意します)、もしくはサーバーのフォルダ自体のフォルダやファイルの実行権限あたりを見直すのがいいと思います。

ひとまず、上のようにphp-fpmが動作することが確認できれば、今度はnginxの設定に移ります。

nginxの設定

nginxの設定は主に次の2つのファイル・フォルダで設定します(Debianの場合、他のOSは。

  • /etc/nginx/nginx.conf
  • /etc/nginx/conf.d/*.conf

サーバー全体に関する設定は主に1つ目のnginx.confファイルで設定します。そして、ドメインごとや個別の細かい設定などに関してはconf.dフォルダの下に設定ごとに*.confファイルを作成して設定していきます。

デフォルトでは静的ファイル(htmlや画像など)しか動かないので、先ほどのphp-fpmと連携してWeb上でPHPの動的ファイルも動作できるようにしていきます。

ここで1つ注意しておきたいのは、php-fpmのデフォルト実行ユーザーはwww-dataですが、nginxの実行ユーザーはnginxになっていることです。php-fpmの設定でも触れましたが、この実行ユーザーと権限に注意しておかないと、nginxとphp-fpmの連携がとれずに、WebからPHPがうまく動作しません

それでは、WordPressを動作させるための最小限の設定をしていきます。まずはnginxの基本設定ファイルnginx.confの変更です。

$ sudo vi /etc/nginx/nginx.conf

nginx.confの中身は次のように1行目の実行権限をnginx->www-dataに変更するだけです。ひとまず、それ以外はデフォルトのままにしておきます。

#user  nginx; # コメントアウトもしくは削除
user www-data www-data;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

実行ユーザーだけを変更してnginx.confの基本設定としておきます。ちなみに、上の設定ファイルにある次の行の指定のおかげで、conf.d下の個別の設定ファイル(*.conf)を読み込むようになります。

    include /etc/nginx/conf.d/*.conf;

次に、WordPressを動かすためのPHP関連も含めたファイルをconf.d下に作っていきます。その前にデフォルト設定のdefault.confの名前を変更して無効にしておきます(設定ミスの原因を把握しやすくします)。

$ cd /etc/nginx/conf.d
$ sudo mv default.conf default.conf.org

ここでは、conf.dの下にwordpress.confという名前でWordPressに関する最小設定のファイルを作成します。

$ sudo vi /etc/nginx/conf.d/wordpress.conf

wordpress.confの中身は次のようになります。

server {
    root    /var/www/wordpress;
    index   index.php;

    listen  80 default_server;

    try_files $uri $uri/ /index.php?$args;

    location ~ \.php$ {
        fastcgi_pass    unix:/var/run/php5-fpm.sock;
        fastcgi_index   index.php;
        fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include         fastcgi_params;
    }
}

server {…}の中身にドメインごとや個別の設定を記述していきます。

まず、rootにはWordPressをインストールしたフォルダを指定します(ここでは/var/www/wordpressにインストールしたと仮定)。try_files行はWordPressのパーマリンク設定用です。

location (…) {…}については階層やファイル名などに応じて動作を切り替える設定を記述します。主に、先ほどインストール・設定したphp-fpmに関する内容を記述します。気を付けるのはfastcgi_passで指定するphpの受け渡し先です。ここでは、先ほどphp-fpmで設定したunixソケットを指定します。

以上がWordPress用のnginxの最小限の設定ファイルになります。nginxの細かい設定や意味については次のサイトをご参考ください。

設定ファイルが作成できたら、ファイル内容に間違いがないことをチェックします。

$ sudo nginx -t -c /etc/nginx/nginx.conf
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

最後に『successful』と表示されれば設定ファイルは正しく設定できています。もし、nginx.confやwordpress.confに間違いがあると、間違いのある行を教えてくれますので修正します。(ちなみに、default.conf.orgに名前を変えたので、このファイルは末尾が.confでないので読み込まれません)

設定ファイルに問題がなければ、nginxを再起動します。

$ sudo service nginx restart

サーバー再起動後に設定したIPアドレスへブラウザーで訪れると、WordPressが動作していると思います(おまけ1 WordPressのインストール & 設定に簡単なWordPressのインストールを書いています)。

実際の運用を考えると、最小構成の設定内容だけではサーバーの応答性や挙動、ログの扱いなどに改善点があります。実際にベンチマークでWebサイトの測定をするとスコアがぱっとしません。この改善に関しては、おまけ3 nginxの改善に記載したいと思います。

nginxでバーチャルホスト

1つのサーバーで複数のドメインとサイトを運営する方法です。Apacheではバーチャルホストと呼ばれる手法で、nginxも同じようにドメイン名に応じて表示するサイトを切り替えることができます。

ここではnginxの1つのサーバー上に、2つの別々のWordPressのサイトと2つのドメイン名を使って表示を分ける方法を紹介します。

ドメイン名ごとに設定ファイルを作成

nginxでは設定ファイルのserver {…}内にserver_nameにドメインを記述することでバーチャルホストを実現できます。

ここでは次のようなドメイン名とサイトのファイル場所を例として考えます。

  • サイト1
    • ドメイン名 foo.com
    • ファイル場所 /var/www/foo
    • 静的ファイルのサイト
  • サイト2
    • ドメイン名 bar.com
    • ファイル場所 /var/www/bar
    • WordPressのサイト

この場合、conf.d下に次のようなファイルを作成します(multi.conf)。

$ sudo vi /etc/nginx/conf.d/multi.conf

multi.confの中身にはドメイン名ごとの設定を記述します。

server {
    listen  80 default_server;
    server_name foo.com;

    access_log  /var/log/nginx/foo_access.log;
    error_log   /var/log/nginx/foo_error.log;

    location / {
        root   /var/www/foo;
        index  index.html index.htm;
    }
}

server {
    listen  80;
    server_name bar.com;

    access_log  /var/log/nginx/bar_access.log;
    error_log   /var/log/nginx/bar_error.log;

    root    /var/www/bar;
    index   index.php;

    try_files $uri $uri/ /index.php?$args;

    location ~ \.php$ {
        fastcgi_pass    unix:/var/run/php5-fpm.sock;
        fastcgi_index   index.php;
        fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include         fastcgi_params;
    }
}

server {…}という記述ごとに上のようにserver_nameにドメイン名を記載すると、ブラウザー(クライアント)からリクエストされたドメインに応じてnginxがデータを返信します。

listen行のポート番号の後ろにdefault_serverと追記すると、デフォルト(記載したドメイン以外の場合やIPアドレス直接からのリクエストなど)はこの記載のあるserver {…}の内容が反映されます。もし、この記述がない場合は、最初に読み込まれたserver {…}がデフォルトになります。

上のように、各ドメインごとにserver内に設定を記述することで、ドメイン名に応じたサーバーの動きを設定できます。上の例では、foo.comでアクセスされた場合は/var/www/fooフォルダ以下の静的なサイトを表示するようにして(PHPは動作しない)、bar.comでアクセスすると/var/www/barフォルダ以下のWordPressを表示させることができます。

また、上記のようにログデータをドメイン名ごとに分けることで、あとでアクセス調査や不具合があった場合に調査しやすくなります。

上の例では2つでしたが、3つ以上になってもserver {…}の記述を追加していくことで複数のドメインとサイトを1つのサーバーで運用できます。

参考

以上、nginxのインストールからはじまってバーチャルドメインの設定までの簡単なやり方を紹介させていただきました。これ以降については、おまけとして補足的な話をメモしておきたいと思います。

おまけ1 WordPressのインストール & 設定

MySQLを設定して、WordPressをダウンロードして起動するまで。

  • データベース名 hoge
  • ユーザー名 foo
  • パスワード password
$ mysql -u root -p
mysql> create database hoge;
mysql> grant all privileges on hoge.* to foo@localhost identified by 'password';
mysql> exit

$ wget https://ja.wordpress.org/latest-ja.tar.gz
$ tar zxvf latest.tar.gz
$ sudo chown -R www-data.www-data wordpress
$ find wordpress -type d | sudo xargs chmod 775
$ find wordpress -type f | sudo xargs chmod 664

以上の作業後、ブラウザーでアクセスすると次の画面。

20151207_2

「さあ、始めましょう!」からWordPressの初期設定をすると完了。(wp-config.phpが生成されます)

参考

おまけ2 Webサイトのベンチマーク

Webサーバーを設定する上で、サイトのベンチマークは欠かせません。ベンチマークやチェックツールで検証することで『効果がある』と判断できるからです。そして、Webサイトの場合はサーバーの設定が大事なのはもちろんですが、ユーザー体験(読み込みや表示速度など)はサイト作りや構成自体にも大きく左右されるので、その点もチェックが大事です。

ここでは、冒頭で紹介した次の4つのWebサイトのチェックツールを紹介したいと思います。

Apache Bench

WebサーバーのApacheに付属するベンチマークツールです。コマンドラインからサーバーにリクエスト(負荷)をかけて、その応答性からチェックします。

$ ab -n 100 -c 10 http://foo.com/

-nにはリクエストの総数、-cには同時に発行するリクエスト数を所定のサイトにリクエストします。上の例では10人のユーザーが10回(10×10=100)、http://foo.com/にリクエストをかけています。

ベンチマークとしては次のような応答がかえってきます。

This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking akkagi.info (be patient).....done


Server Software:        nginx
Server Hostname:        akkagi.info
Server Port:            80

Document Path:          /
Document Length:        19823 bytes

Concurrency Level:      10
Time taken for tests:   5.319 seconds
Complete requests:      100
Failed requests:        0
Total transferred:      2011300 bytes
HTML transferred:       1982300 bytes
Requests per second:    18.80 [#/sec] (mean)
Time per request:       531.934 [ms] (mean)
Time per request:       53.193 [ms] (mean, across all concurrent requests)
Transfer rate:          369.25 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       52  143 156.9    122    1196
Processing:   241  373 142.4    341    1039
Waiting:       58  150  56.6    140     424
Total:        368  516 199.4    462    1537

Percentage of the requests served within a certain time (ms)
  50%    462
  66%    479
  75%    504
  80%    506
  90%    641
  95%    925
  98%   1484
  99%   1537
 100%   1537 (longest request)

注目したいのは『Failed requests』と『Time per request』の部分です。

Failed requestsには応答に失敗した回数が表示されます。0が理想ですが、応答が追い付かなかったり何らかのエラーが発生するとここにリクエストの失敗した回数が表示されます。

Time per requestは1秒間に応答できるリクエスト数になります。例えば、上の場合は18.80[#/sec]とあるので、1秒間に18.8回のリクエストがさばけることになります。この数値がわかることで、実際のサイトにおいて「どれだけの負荷(同時アクセスなど)に耐えられるか?」がわかります。

1つ注意しておきたいのは、abコマンドを使う場合は同じサーバー上ではなく、別のクライアントから実行することです。というのは、同じサーバー上で実行するとネットワークを経由しないベンチマークとなるので、非現実的な数字が出たりします(Requests per secondに5000[#/sec]など)。自分のPCなどからabコマンドで出てきた数字の方が現実に近いデータになると思います。

Chromeの検証ツール『Network』のファイル読み込み時間

20151207_3

Chromeの検証ツールを使ってサーバーの応答をチェックしてみます。Chrome上で右クリック→『検証』もしくは画面右上のメニューボタン→その他のツール→デベロッパーツールもしくはCtrl+Shift+Iから検証ツールが立ち上がります。

検証ツールが立ち上がると通常は『Elements』というhtmlのソース解析になりますが、ここで画面右上の『Network』を選択すると上のような画面になります。

ここで、調査したいWebサイトを再読み込みすると、各ファイルの読み込み時間やリクエストの応答が確認できます。これを利用して各ファイルの読み込み時間や応答内容をチェックすることでサーバーの動作を確認することができます(各ファイル名をクリックするとRequest HeadersやResponse Headersなどのサーバーとのやりとりも確認できます)。

「ファイルが圧縮されて送れているか?」や後述のおまけ3 nginxの改善で出てくるキャッシュに関しても、この応答内容にキャッシュ情報を返すようにすることで「キャッシュが働いているか?」などもチェックすることができます。

GoogleのPageSpeed Insights

20151207_4

Googleが提供しているWebサイトのスピードチェッカーです。

Webサイト自体のチェックツールですが、サーバーに関しても

  • 応答時間
  • ファイルの圧縮

上の項目で評価できます。どちらもサーバーの設定を改善することで効果がありますので、簡単なサーバーのチェックにも利用できます。

もちろん、Webサイト自身の作り方や構成の方の比重が大きいので、PageSpeed Insightsの点数を稼ぎたい場合はWebサイト自身を見直す方が効果が大きいです。

GTmetrix

20151207_5

GTmetrixは上のPageSpeed Insightsと同じで、Webサイトのベンチマークスコアが出るサイトです。

サイトの応答性などを数値化してくれます。また、改善点があれば指摘してくれますので、サーバー側に問題があれば、設定を変更して検証することができます。

以上、4つのWebサイト・Webサーバーのチェックツールを紹介しました。サーバーの設定をチェックしたり設定変更をしたときの改善具合の評価に活用してみてください。

おまけ3 nginxの改善

記事では手順や流れを理解するために、細かい設定は省略して紹介しました。実際のWebサーバーではもう少し細かい設定を追加して、より応答速度を向上したりサーバーの負荷を下げるようにしていきます。

ここでは主に次の2つの手法について紹介します。

  1. ファイルの圧縮
  2. キャッシュを使った改善

ファイルの圧縮

サーバーとクライアントがデータをやり取りするときに、転送するファイルを圧縮することでデータ量を削減させます。これによって応答速度が改善します。

ファイル圧縮の設定はサーバー全体に反映させるために、nginx.confファイルを修正します。

$ sudo vi /etc/nginx/nginx.conf

nginx.confのファイルのhttp {…}に次の内容を追記します。

...
http {

...

    gzip                on;
    gzip_http_version   1.0;
    gzip_min_length     1024;
    gzip_buffers        4 8k;
    gzip_comp_level     1;
    gzip_types          text/plain
    #                    text/html
                        text/xml
                        text/css
                        application/xml
                        application/xhtml+xml
                        application/rss+xml
                        application/atom_xml
                        application/javascript
                        application/x-javascript
                        application/x-httpd-php;
    gzip_disable    "MSIE [1-6]\.";
    gzip_disable    "Mozilla/4";
    gzip_proxied    any;
    gzip_vary       on;

...

}

gzipをonにして、関連する設定を記載しています。主にテキストデータ(htmlやcss)を対象にして圧縮するようにしています(nginxはgzipをonにするとtext/htmlがデフォルトですでに記載されていることになるのでコメントアウトしています)。

gzip_min_lengthで圧縮対象のファイルサイズを1024byte(1KB)にしていますが、扱うサイトやサーバーの応答性によって変更します。特に、ファイルを圧縮するとCPUを消費しますので、サーバーのCPUコストが負担になる場合はファイルサイズを大きくしてあげて、小さいファイルは圧縮せずにCPUに負荷をかけないようにした方がいいかもしれません。

また、gzipに対応していないIE6以下のブラウザーやMozilla/4に関しては圧縮せずにデータを転送するようにしています。

以上、ファイル圧縮の設定が完了したら、サーバーを再起動します。

$ sudo service nginx restart

ChromeでWebサイトにアクセスします。検証ツールで下の画面のように『Response Headers』に『Content-Encording: gzip』と記載があればファイル圧縮がされていることがわかります。

20151207_6

キャッシュを使った改善

nginxのリバースプロキシというproxy cacheを利用してサイトにキャッシュ技術を取り入れます。

WordPressに代表されるPHPなどを使った動的なサイト(ページ)は、ブラウザーのリクエストごとに毎回プログラム(PHPなど)を解釈して実行しています(CPUを消費しています)。1つ1つのリクエストを見ると大したことはなさそうですが、Webサイトに同時にアクセス(リクエスト)されるとCPUの消費が激しくなって負荷となり、サイトの応答が遅くなってしまいます(最悪はサーバーが落ちてしまいます)。

そこで、動的なページをキャッシュすることでCPUに負荷をかけずにリクエストを返すことができるようになります。特に、WordPressで主流なブログ型サイトでは、ユーザーによらずにリクエスト(url)に応じて応答する構成になっているので、キャッシュ機能は特に有効です。(逆に、SNSやログイン機能があるサイトは、ユーザーごとにページ表示が異なるのでリクエストごとにページ生成が発生し、キャッシュ効果が小さいです。)

もともと、nginxはWebサーバーだけでなくキャッシュサーバーに利用することも可能で、このような負荷軽減や分散にも対応できるツールになっています。

それでは、nginxでキャッシュを利用する仕組みを設定していきます。

$ sudo vi /etc/nginx/conf.d/cache.conf

まずは、cache.confとしてキャッシュ用のファイルを作成することにします。cache.confの中身の概要は次のような2段構成になります。

proxy_cache_path    /var/cache/nginx/foo levels=1 keys_zone=foo:64m;

server {
    listen  80;
    server_name foo.com;

    ...
    location / {
        proxy_cache  foo;
        proxy_pass   unix:/var/run/nginx_foo.sock;
    }
}

server {
    listen unix:/var/run/nginx_foo.sock;

    ....
}

1行目のproxy_cache_pathでは、サイトの全体的な設定部分でproxy cacheの設定をしています(あまり見られない書き方ですが、server {..}記述の外に書くことで、http {…}直下に書いたことと同義になり、個別ファイルにすることでnginx.confファイルから切り離して個別にproxy cacheの設定ができます)。

cache.confにserver {…}を2つ記述して

  • s1 : 通常の80番ポートで待つサーバー(キャッシュ用)
  • s2 : 動的なページ生成用サーバー(キャッシュがない場合)

このように役割ごとにサーバーの設定をしていきます。

20151207_7

基本はs1が80番ポートで外部c(client)からのリクエストを待ち受けます。80番ポートで1度リクエストを受けると、そのリクエストをunixソケットで待つ2つ目のサーバーs2に転送します(TCPのポートも指定できます)。s2でPHPなどの動的な処理を実行し、それをs1へ返します。

s1はs2から応答が返ってくると、リクエストのあったクライアントへその情報を返します。その時、s1は先ほどの情報をキャッシュしておき、別のクライアントから同じリクエストがあればそのままキャッシュを返すようにします。

このキャッシュを利用することで動的なページを作る必要がなくなり、CPUの負担が抑えられるので、サーバー全体への負荷が下がります。

場合によっては、動的なページをApacheにしたり物理的に別のコンピューターを割り当てたりしてサイト全体の負荷軽減・分散や最適化をはかります。

最後に、具体的なcache.confの例を紹介して終わりたいと思います。

proxy_cache_path    /var/cache/nginx/foo levels=1 keys_zone=foo:64m;

server {
    root    /var/www/foo;
    index   index.php, index.html index.htm;
    charset utf-8;

    listen  80;
    server_name foo.com;

    access_log  /var/log/nginx/foo_access.log;
    error_log   /var/log/nginx/foo_error.log;

    proxy_set_header    Host $host;
    proxy_set_header    X-Real-IP $remote_addr;
    proxy_set_header    X-Forwarded-Host $host;
    proxy_set_header    X-Forwarded-Server $host;
    proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_cache_valid   200 404 30m;

    add_header X-Cache  $upstream_cache_status;

    location ~ /\. { deny all; access_log off; log_not_found off; }
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        log_not_found   off;
        access_log      off;
        expires         10d;
    }

    set $do_not_cache 0;
    # wordpressの管理画面系はcacheなし
    if ($uri ~* "\.php$") {
        set $do_not_cache 1;
    }

    location / {
        proxy_cache         foo;
        proxy_no_cache      $do_not_cache;
        proxy_cache_bypass  $do_not_cache;
        proxy_cache_key     "$scheme$proxy_host$request_uri";
        proxy_pass          http://unix:/var/run/nginx_foo.sock;
    }
}

server {
    root    /var/www/foo;
    index   index.php;

    listen unix:/var/run/nginx_foo.sock;

    try_files $uri $uri/ /index.php;

    access_log  /var/log/nginx/foo_access_sock.log;
    error_log   /var/log/nginx/foo_error_sock.log;

    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        expires 24h;
        log_not_found off;
    }

    location ~ \.php$ {
        fastcgi_pass    unix:/var/run/php5-fpm.sock;
        fastcgi_index   index.php;
        fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include         fastcgi_params;
    }
}

s1に相当する部分では概要に次の内容を追加しています。

  • ログ設定
  • proxyにヘッダー追加
  • .で始まるファイル無視(.htaccessなど)
  • 画像ファイルのキャッシュ期間の設定
  • WordPressの管理画面をキャッシュしない設定
  • proxy cache設定

また、細かいテクニックになりますがadd_headerで始まる次の行を追加することで

    add_header X-Cache  $upstream_cache_status;

Chromeの検証ツールの『Network』→『Response Headers』にキャッシュに関するヘッダーが付与されます。

キャッシュされているとき
X-Cache:HIT

キャッシュされていないとき
X-Cache:MISS

これを確認することで、キャッシュ機能がきちんと動作しているかどうかが判定できます(同じページを2回読み込むとわかります)。

s2に相当する部分は次を追記しています。

  • ログ設定
  • 画像ファイルのキャッシュ期間の設定
  • php-fpmに関する設定

以上の設定でnginx上にキャッシュをしながらWordPressが動作するようになります。

さらに、404系の500系のエラー対応についても追加することで、よりよいサーバーになると思います。また、php-fpmやnginx自体のプロセス数やメモリの割り当てなども調整することで、より応答性のいいサーバーを目指すことも可能だと思います。

参考

おわりに

1回目のさくらVPSへ移行に続いて、今回はnginxでWordPressが使えるWebサーバーの設定を紹介しました。またまた、すごい長文になってしまいましたが、個人的なメモと割り切ってこのまま残します。

ぼくのサイト規模(1,000PV/日)くらいではApacheでもnginxでもどちらでもいい気がしましたが、いろいろと勉強になったので結果的にはOKだと思います。

あと、さくらVPSの1Gプランにしましたが、ぼくの使い方だと512プランでも十分だったかもと思う今日この頃。