タグ別アーカイブ: Apache

mod_rewrite サンプル集/楽

mod_rewrite サンプル集

mod_rewrite はすげー色んなことができて楽しい。
でもけっこう難しい。
そこで、オイラ用メモで簡単なサンプル集をば。

シンプルなリダイレクト例

/hoge/ を /fuga/ に rewrite(リダイレクト)する。

RewriteEngine on
RewriteRule ^/hoge/$ /fuga/

/hoge/ 以下を /fuga/ 以下にまとめて rewrite(リダイレクト)する。

RewriteEngine on
RewriteRule ^/hoge/(.*)$ /fuga/$1

/hoge/ 以下で末尾が .jpg のリクエストのみを /fuga/ 以下に rewrite(リダイレクト)する。

RewriteEngine on
RewriteRule ^/hoge/(.*.jpg)$ /fuga/$1

/hoge/ 以下で末尾が .jpg か .gif のリクエストのみを /fuga/ 以下に rewrite(リダイレクト)する。

RewriteEngine on
RewriteRule ^/hoge/(.*).(jpg|gif)$ /fuga/$1.$2

/cgi-bin/hoge/fuga を /cgi-bin/example.cgi?q=hoge&opt=fuga に rewrite(リダイレクト)(いわゆる、動的アドレスを静的アドレスに変換するってやつ)

RewriteEngine on
RewriteRule ^/cgi-bin/([0-9A-Za-z]+)/([0-9A-Za-z]+)$ /cgi-bin/example.cgi?q=$1&opt=$2


リダイレクト時のブラウザのURL欄

mod_rewrite で rewrite(リダイレクト)処理を行ったとき、以下のようにサーバパスで rewrite(リダイレクト)させると、ブラウザのURL欄は書き換わらない。

RewriteEngine on
RewriteRule ^/hoge/$ /fuga/

例えば、
http://www.example.com/hoge/ にアクセスすると、
http://www.example.com/fuga/ の中身が、
URL欄は http://www.example.com/hoge/ のまま表示される。

しかし、以下の例では、リダイレクトと同時にURL欄が書き換わる。

RewriteEngine on
RewriteRule ^/hoge/$ /fuga/ [R=301]

RewriteEngine on
RewriteRule ^/hoge/$ /fuga/ [R=302]

RewriteEngine on
RewriteRule ^/hoge/$ http://www.example.com/fuga/

最後の URL にリダイレクトさせるパターンは、同じサーバ内の URL であっても、飛び先を URL で記述するとブラウザのURL欄が書き換わります
同一サーバ内であれば、URLにリダイレクトさせると無駄にログも増えるのであまりオススメしません。


%2F問題

Apache1.X 系で mod_rewrite を使う場合、URLに「%2F」が含まれると思い通りに動作しない問題があります。
(Apache2.X 系でも同様ですが、Apache2.0.46 以降では「AllowEncodedSlashes On」により回避できます。)

例えば、以下のような書き換えを記述したとします。

RewriteEngine on
RewriteRule ^/keyword/(.*)$ /cgi-bin/script.cgi?k=$1

想定としては、
http://www.example.com/keyword/hogefuga というアクセスに対して
http://www.example.com/cgi-bin/script.cgi?k=hogefuga の結果を返します。

hogefuga の部分が色々と変化するわけです。

この際、
http://www.example.com/keyword/hogefuga/hage
http://www.example.com/cgi-bin/script.cgi?k=hogefuga/hage となりますが、

http://www.example.com/keyword/hogefuga%2Fhage
http://www.example.com/cgi-bin/script.cgi?k=hogefuga%2Fhage とならず、404エラーになります

直接、
http://www.example.com/cgi-bin/script.cgi?k=hogefuga%2Fhage にアクセスするとこの問題は起きません。

先にも書きましたが、Apache2.0.46 以降では httpd.conf に「AllowEncodedSlashes On」を記述することにより回避できます。
しかし、Apache1.X の環境ではなかなか回避できずにはまる要素だと思います。


アクセスを拒否する

どこかにリダイレクトするのではなく、特定のアクセスにエラーを返せます。

.htaccess へのアクセスを拒否する。

RewriteEngine On
RewriteRule .htaccess – [F]

/hoge/ 以下へのアクセスに 403 Forbidden を返します。

RewriteEngine On
RewriteRule ^/hoge/.* [F]

/hage/ 以下へのアクセスに 410 Gone を返します。

RewriteEngine On
RewriteRule ^/hage/.* [G]


複数の RewriteRule

RewriteRule は複数かけます。

/hoge/ 以下を /fuga/ 以下にリダイレクとした上に /fuga/hage/ 以下のものは /foo/ 以下にリダイレクトする。

RewriteEngine On
RewriteRule ^/hoge/(.*) /fuga/$1
RewriteRule ^/fuga/hage/(.*) /foo/$1

上の例で、/hoge/ 以下を /fuga/ 以下にリダイレクとさせた時点で処理を終わらせる、つまり次のリダイレクトを実行させないようにするには [L] を付加します

RewriteEngine On
RewriteRule ^/hoge/(.*) /fuga/$1 [L]
RewriteRule ^/fuga/hage/(.*) /foo/$1


RewriteRule のオプション

これ以外にもいろいろありますが。

HTTPステータスコードを吐く [R=ステータスコード]

RewriteEngine On
RewriteRule ^/hoge/(.*) /fuga/$1 [L,R=301]
RewriteRule ^/fuga/hage/(.*) /foo/$1

大文字、小文字を区別しない [NC]

RewriteEngine On
RewriteRule ^/hoge/(.*) /fuga/$1 [NC,L]
RewriteRule ^/fuga/hage/(.*) /foo/$1


ある条件が揃ったらリダイレクト

RewriteCond を使えば、ある条件に合致したときだけリダイレクトするということも、もちろん可能です。

HTTP_HOST が www.example.com だったら RewriteRule を適用する。

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteRule ^/(.*) /$1

HTTP_HOST が www.example.com じゃなかったら RewriteRule を適用する。

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.example.com$
RewriteRule ^/(.*) /$1

HTTP_HOST が www.example.com で HTTP_USER_AGENT に MSIE が含まれていたら RewriteRule を適用する。

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteCond %{HTTP_USER_AGENT} MSIE
RewriteRule ^/(.*) /$1

RewriteCond を複数並べると AND でつながっていく。OR にしたい場合は [OR] をつける

HTTP_HOST が www.example.com であるか、または HTTP_USER_AGENT に MSIE が含まれていたら RewriteRule を適用する。

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.com$ [OR]
RewriteCond %{HTTP_USER_AGENT} MSIE
RewriteRule ^/(.*) /$1

RewriteCond の条件で大文字、小文字を区別しない場合は [NC] をつける。

HTTP_USER_AGENT に MSIE や msie や MsIe や MSiE などが含まれていたら RewriteRule を適用する。

RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} MSIE [NC]
RewriteRule ^/(.*) /$1

RewriteCond で対象となる変数には以下のようなものがあります。

HTTP_USER_AGENT / HTTP_REFERER / HTTP_COOKIE / HTTP_FORWARDED / HTTP_HOST / HTTP_PROXY_CONNECTION / HTTP_ACCEPT
REMOTE_ADDR / REMOTE_HOST / REMOTE_USER / REMOTE_IDENT / REQUEST_METHOD / SCRIPT_FILENAME / PATH_INFO / QUERY_STRING / AUTH_TYPE
DOCUMENT_ROOT / SERVER_ADMIN / SERVER_NAME / SERVER_ADDR / SERVER_PORT / SERVER_PROTOCOL / SERVER_SOFTWARE
TIME_YEAR / TIME_MON / TIME_DAY / TIME_HOUR / TIME_MIN / TIME_SEC / TIME_WDAY / TIME
API_VERSION / THE_REQUEST / REQUEST_URI / REQUEST_FILENAME / IS_SUBREQ

以上、かんたんな mod_rewrite サンプル集でした。

ここに挙げた機能だけでもいろいろ遊べますが、環境変数を設定したり、外部スクリプトを利用して書き換え処理をしたり、などといったもっと複雑な処理もmod_rewriteでは可能です。
いろいろ試してアーミーナイフの達人目指してください。

広告

さくらVPSとnginxリバースプロクシで最速WordPressブログを作る方法(ベンチマーク付き) | さくらたんどっとびーず

負荷的に厳しくなってきたので sakuratan.biz を Apache(さくらスタンダード)から nginx(さくら VPS 512)に移転しました。
頻発していた 503 もほとんど出なくなって快適です。

Apache から VPS の nginx へ WordPress を移転したいと考えている人もいるかなーと思いましたで、さくら VPS で nginx リバースプロクシを使った WordPress ブログの構築する方法をがっつり書いていきたいと思います。

結構長文になってしまいましたので、先に索引を載せときます。

  1. nginx とは
  2. nginx が速い理由
  3. リバースプロクシ
  4. さくら VPS にインストールするシステム構成
  5. EPEL パッケージリポジトリのインストール
  6. MySQL のインストール
  7. PHP のインストール
  8. nginx のインストール
  9. nginx と PHP FastCGI の設定
  10. WordPress のインストール
  11. Nginx Proxy Cache Purge WordPress プラグインのインストール
  12. ベンチマーク
  13. 参考サイト

nginx が速い速いとだけ言われてもいまいち腑に落ちない方もいらっしゃるかと思いましたので、最初の方の章は nginx 自体の説明にしました。前置きは置いといてとりあえずインストール方法を知りたい方は、『さくら VPS にインストールするシステム構成』あたりからどうぞ。ちなみにさくら VPS は CentOS ですので、他のレン鯖でも OS が同じなら同じ手順でインスコできると思います。

サンプルのファイルをまとめた zip を nginx-examples.zip に置いてますので、とりあえずファイルだけ欲しいって人はこちらをどうぞ。

あと、なんとなくあった方が良いかなーと思いまして Apache と nginx のベンチマークもしてみました。結果の方は最後の方に載せてますが、結論だけ言えば nginx は多い日も安心のロリエセーフティロング高性能です。

nginx とは

まず最初に nginx の wiki から引用します。

Nginxはその高いパフォーマンスと安定性、豊富な機能、設定の容易さ、消費リソースの低さで知られています。

NginxはC10K問題に取り組むべく開発された一握りのサーバのうちの一つです。従来のサーバとは異なり、Nginxはリクエストの処理をスレッドに依存していません。その代わりにもっとスケーラブルな(非同期の)イベント駆動アーキテクチャを使用しています。このアーキテクチャはメモリ使用量が少ないだけでなく、最も重要な事として、稼働時のメモリ使用量が予測可能であるということです。

http://wiki.nginx.org/NginxJa

C10K問題とは、ハードウェアは安くなって大量のクライアントを同時処理できるようになったけど、OS やサーバプログラムの実装がボトルネックになってて1万(=10K)クライアント以上は処理できない(*´・ω・)(・ω・`*)ネー、という問題です。(Web2.0の先にあるC10K問題 - @IT の説明が分かりやすいと思いますので詳しく知りたい方はどうぞ。)

上の概要に書いてますが、nginx はC10K問題を解決すべく作られた新しいウェブサーバですので、Apache 等の従来からあるウェブサーバと比べて本質的にスケーラブルなシステムとなっています。

nginx が速い理由

開発されてる方でしたら、nginx が速いと言う話をどこかで聞いた事があるかと思います。

実際のところ nginx が速いと言うよりも、nginx は Apache などの従来のサーバと比べ少ないリソースで複数の HTTP リクエストを処理できるように設計されているため、サーバが負荷の高い状態になっても性能が劣化しにくい、と言うのがより正確だと思います。

ということで、nginx が高負荷状態に強い仕組みについて簡単に説明しようと思います。


nginx では外部からのネットワークコネクションを受け付けるプロセスをマスタープロセス、HTTP リクエストに対するレスポンスを返すプロセスをワーカープロセスと呼びます。マスタープロセスはコネクションを受け取ると稼働中のワーカープロセスのいずれかに HTTP レスポンスを返す処理を行うよう指示します。(マスター/ワーカープロセス構成自体は TCP/IP ベースの Unix daemon の一般的な構成ですので速い理由と関係ありません。)

nginx のワーカープロセスは(kqueue (FreeBSD 4.1以降)/epoll (Linux 2.6以降) などのカーネルによって異なる)非同期 I/O 通知メソッドを使い、複数のリクエスト/レスポンスを一つのプロセスで平行して同時に処理します。


一方、Apache などの従来のウェブサーバでは、リクエストを応答するプロセスは同期 I/O を使います。同期 I/O を使うと一つのワーカープロセスは複数の HTTP リクエストを同時に処理することができません。複数の HTTP リクエストを処理する場合は、先行するリクエストが完了するのを待って順次処理していきます。


Apache の場合、サーバにアクセスが集中し応答すべきリクエストが増えてきて、既に起動しているワーカープロセスだけでは処理が追いつかなくなると、新しいワーカープロセスを起動したり/新しいワーカープロセスを起動できない場合応答中のレスポンスの完了を待ってからリクエスト処理を開始することになります。

ワーカープロセスはそれぞれある程度のメモリを使用しますので、システムリソースから決まる同時応答可能な上限を越えると(スラッシングが発生するなどの原因で)ウェブサーバ全体の性能が急激に悪化します。(MPM worker を使って Apache をマルチスレッドで動かす場合も、1スレッドに対してそれなりのシステムリソースが必要となりますので、高負荷状態においてこの問題はそれほど改善しないです。)

それに対して nginx の場合、非同期 I/O を使って一つ(設定により増やせますがあくまで少数)のワーカープロセスですべてのリクエストを処理するよう設計されいます。必要なシステムリソースが少ないので、Apache では性能が悪化する局面でも極端に性能が悪化しません。なので nginx は速い、ということになります。


ちなみにワーカープロセスが行うレスポンス処理については Apache と nginx で特に性能に差がある訳ではありませんので、1リクエスト当たりの実処理時間はだいたい同じです。(一部のベンチマークではレスポンス自体は nginx の方が遅いという数字が出ていますが、自分のサイトで測った限りでは意味のある差はでませんでした。いずれにしても今時のサーバだと、ワーカープロセスの性能の優劣は特に気にする必要はないと思います。)


 _______________________
     <○√  くそっもうだめか・・!!
      くく   リクエストが多すぎる、Apacheでは処理しきれない・・・
 ________________________________
        ~|
         \○    大丈夫か?BOY
            ∥\
   <○>     ∥/
    ∥    / |
    >>    \ |
 nginxさん!!

リバースプロクシ

リバースプロクシとは、ざっくり言いますとウェブサーバをまるごとキャッシュする機能です。

WordPress などを動かす場合、アプリケーションを実行する部分がウェブサーバのボトルネックとなります。このボトルネックを解消するために、WP Super Cache などのアプリケーションレベルでのキャッシュや mod_cache などのウェブサーバレベルでのキャッシュがありますがウェブサーバと別にリバースプロクシサーバを用意しプロクシサーバがキャッシュを行うという解決方法もあります。


リバースプロクシを加えたウェブサーバの処理は下図のようになります。

リバースプロクシサーバがフロントエンドとなり、80 番ポートで外部からの HTTP リクエストを受け取ります。
リクエストされた URL がキャッシュされていれば、プロクシサーバはキャッシュ済みのレスポンスを返します。
キャッシュされていなければウェブサーバへリクエストを転送し、レスポンスをキャッシュして返します。

プロクシサーバには PHP スクリプトを実行する機能などは不要ですので、通常ウェブサーバよりも高速に動くよう実装されています。システム構成にリバースプロクシを加えることで全体での処理能力が高くなります。

nginx をリバースプロクシにする場合、リバースプロクシの設定が簡単なので(一つの設定ファイルにフロントエンドのプロクシサーバとバックエンドのウェブサーバの設定を記述できます)、とりあえずリバースプロクシも立てとけって感じです。


ちなみに、nginx をリバースプロクシに、バックエンドのウェブサーバは元から動いていた Apache そのまま、といった構成も可能です。VPS(特にさくら VPS 512)ではメモリサイズ的にこの構成は少し厳しいと思いますが、リソースにある程度余裕がある状況では費用対効果の高い性能改善策になると思います。

さくら VPS にインストールするシステム構成

ということで、nginx 自体の説明はこの辺にして、さくら VPS で nginx リバースプロクシを有効にした WordPress ブログのインストール方法について説明していきたいと思います。

まずさくら VPS のデフォルト OS は CentOS でして、OS はそのまま使う設定で話を進めます(VPS に Debian 入れたりする人は nginx の How To 記事なんか見なくても自分で設定できると思いますし)。CentOS ならさくら VPS 以外のサーバでもだいたい同じような手順でインスコできると思います(プレインストールされている yum パッケージの構成やバージョンが違う場合、一部異なる手順になるかもしれませんが)。


インストールするシステム構成はこんな感じです。リバースプロクシ/ウェブサーバともに nginx を使います。nginx には PHP を実行する機能がありませんので、FastCGI サーバとして PHP を実行します。

  • nginx 1.0.6 + Cache Purge plugin
  • PHP 5.3.3 + FastCGI + eAccelerator
  • MySQL 5.0.77
  • WordPress 3.2.1-ja

MySQL は yum のパッケージから普通にインスコします。

PHP は最近 yum に追加されたっぽい php53 パッケージを使います。eAccelerator があった方が良いのですが、php53 系列には eAccelerator のパッケージが無いのでこれだけソースからインスコします。

nginx はソースからビルドしてインスコします。nginx のパッケージが EPEL リポジトリにあるのですが、WordPress を動かす場合パッケージ版の nginx には含まれていない Cache Purge プラグインが欲しいので、パッケージは使いません。(nginx にプラグインを追加する場合はビルド時に組み込む必要があります。)


以下、EPEL のインスコ、MySQL インスコ/起動、PHP インスコ、nginx インスコ、nginx / PHP FastCGI の設定、WordPress インスコ…みたいな順番で書いてます。知ってるところは適当に読み飛ばしてください。

特に明記しない場合すべて root で作業を行う前提で書いています。まずサーバにログインして su するか sudo してください。

EPEL パッケージリポジトリのインストール

最初に EPEL パッケージをインスコします。EPEL の公式サイト から epel-release-5-4.noarch.rpm をダウンロードして rpm コマンドでインスコします。(EPEL 6 系列は CentOS にはインストールできませんので epel-release-5-4.noarch.rpm もしくはバージョン 5 系列の最新版をインストールしてください。)

wget http://download.fedoraproject.org/pub/epel/6/i386/epel-release-54.noarch.rpm
rpm -Uvh epel-release-54.noarch.rpm

EPEL パッケージのインスコ方法も含めて、yum 関係で VPS を借りたら最初にしといた方が良い作業が ウェブ開発者のための、1時間でできるLAMP環境構築術(CentOS編) – さくらインターネット創業日記に書かれてますので、よく分からない人はまずはこちらをご覧ください。

MySQL のインストール

MySQL は yum パッケージをインスコします。

yum install mysql mysql-server

インスコしたらサーバを起動し、chkconfig でリブート時に MySQL サーバが立ち上がるように設定します。

/etc/init.d/mysqld start
/sbin/chkconfig –level 345 mysqld on

PHP のインストール

yum から php53 パッケージをインスコし、eAccellaretor だけソースからビルドします。

yum install php53 php53-cli php53-xml php53-mysql php53-mbstring php53-devel

php53-xml は要らないような気もしますが検証するの忘れてましたのでとりあえずインストールするということで。

PHP をインスコできたら、eAccellaretor のソースコードを SourceForge からダウンロードして展開します。(eAccellaretor のビルド作業については、make install 以外は一般ユーザーで作業しても問題ないです。)

wget http://downloads.sourceforge.net/sourceforge/eaccelerator/eaccelerator-0.9.6.1.zip
unzip eaccelerator-0.9.6.1.zip

ビルドしてインスコします。

cd eaccelerator-0.9.6.1
phpize
./configure –enable-eaccelerator
make
make install

make install で /usr/lib64/php/modules に eaccelerator.so がコピーされますので、/etc/php.ini の extension に eaccelerator.so を追加します。

;;;;;;;;;;;;;;;;;;;;;;
; Dynamic Extensions ;
;;;;;;;;;;;;;;;;;;;;;;

extension=eaccelerator.so

デフォルトでは eaccelerator.cache_dir が /tmp/eaccelerator になっていますが個人的に /var/tmp 以下にしたいので、php.ini の末尾に以下の設定を加えます。デフォルトで問題ない場合はそのままでどうぞ。

[eAccelerator]
eaccelerator.cache_dir = “/var/tmp/eaccelerator”

eaccelerator.cache_dir を作ります。パーミッションはサーバによって適当に変えてください。

mkdir -p /var/tmp/eaccelerator
chmod 777 /var/tmp/eaccelerator

nginx のインストール

nginx をソースからビルドするため、ビルドと実行に必要な yum パッケージをインスコします。

yum –enablerepo=epel install make automake gcc gcc-c++ rpm-build spawn-fcgi
pcre-devel zlib-devel openssl-devel libxslt-devel GeoIP-devel gd-devel

スクラッチからビルドすると init.d のスクリプト等を用意しないといけないので、nginx のソースパッケージ (SRPM) をダウンロードしてから、最新版の nginx を Cache Purge Plugin 付きでビルドするように nginx.spec を書き換えます。

まず EPEL 配布サイトから nginx の SRPM nginx-0.8.54-1.el5.src.rpm をダウンロードします。

wget http://download.fedora.redhat.com/pub/epel/5/SRPMS/nginx-0.8.54-1.el5.src.rpm

SRPM は rpm コマンドでインスコします。/usr/src/redhat/SPEC に nginx.conf が、/usr/src/redhat/SOURCES に SRPM に含まれるファイルが展開されます。

rpm -ivh nginx-0.8.54-1.el5.src.rpm

rpm -ivh を実行する際に mockbuild ユーザーが存在しないためワーニングが出ますが無視して問題ないです。

SRPM をインスコできたら、/usr/src/redhat/SOURCES に最新版の nginx と Cache Purge plugin をダウンロードします。

cd /usr/src/redhat/SOURCES
wget http://nginx.org/download/nginx-1.0.6.tar.gz
wget http://labs.frickle.com/files/ngx_cache_purge-1.3.tar.gz

nginx-1.0.6 で Cache Purge を有効にした nginx.spec を nginx.spec に置いてますので /usr/src/redhat/SPECS ディレクトリにダウンロードしてからビルドします。

cd /usr/src/redhat/SPECS
mv nginx.spec nginx.spec.orig
wget http://sakuratan.biz/nginx/nginx.spec
rpmbuild -bb nginx.spec

ビルドが終われば /usr/src/redhat/RPMS/x86_64 に nginx-1.0.6-1.x86_64.rpm が作成されますので rpm コマンドでインスコします。

rpm -Uvh /usr/src/redhat/RPMS/x86_64/nginx-1.0.6-1.x86_64.rpm

nginx と PHP FastCGI の設定

必要なものがインスコできたら nginx の設定をしていきます。


PHP FastCGI サーバ起動用スクリプトの作成

FastCGI サーバとして PHP を起動するためのスクリプトを php-fastcgi に置いていますので、ダウンロードしてから /etc/init.d に置きます。

wget http://sakuratan.biz/nginx/php-fastcgi
mv php-fastcgi /etc/init.d
chmod 755 /etc/init.d/php-fastcgi

PHP FastCGI サーバの実行ユーザー等を変更する場合は、php-fastcgi スクリプトの以下の箇所を変更してください。なお、以下の説明では 9000 番ポート上で PHP FastCGI サーバを起動する設定で例示しています。また、FastCGI サーバとの通信に TCP/IP ではなく Unix ドメインソケットを使用したい場合は php-fastcgi の spawn-fcgi の起動方法を変更してください(変更方法は各自で調べてください)。

user=nginx
group=nginx
host=127.0.0.1
port=9000
pidfile=/var/run/nginx/php-fastcgi.pid
numclients=5

pidfile を作成するディレクトリは、PHP FastCGI サーバの実行ユーザー(変更しなければ nginx)から書き込める必要がありますので、php-fastcgi スクリプトをデフォルトのまま使う場合は予め /var/run/nginx ディレクトリを作成する必要があります。

mkdir /var/run/nginx
chown nginx:nginx /var/run/nginx

以上の作業が終われば、とりあえず php-fastcgi を起動してみます。

/etc/init.d/php-fastcgi start

エラーが出る場合は設定を確認してください。


nginx.conf の修正

/etc/nginx/nginx.conf にリバースプロクシとバックエンドウェブサーバと PHP FastCGI サーバの設定を追加します。ちょっと長いですが全部貼ります。サーバにファイルを置いてますのでコピペして使いたい方は nginx.conf をどうぞ。

user              nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log;
#error_log  /var/log/nginx/error.log  notice;
#error_log  /var/log/nginx/error.log  info;

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;

    keepalive_timeout  5;

    gzip  on;
    gzip_disable “MSIE [1-6].”;

    proxy_cache_path  /var/cache/nginx levels=1:2 keys_zone=czone:4m max_size=50m inactive=120m;
    proxy_temp_path   /var/tmp/nginx;
    proxy_cache_key   “$scheme://$host$request_uri”;
    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;

    upstream backend {
        ip_hash;
        server 127.0.0.1:8080;
    }

    server {
        listen       80;
        server_name  example.com;

        location / {
            if ($http_user_agent ~* ‘(DoCoMo|J-PHONE|Vodafone|MOT-|UP.Browser|DDIPOCKET|ASTEL|PDXGW|Palmscape|Xiino|sharp pda browser|Windows CE|L-mode|WILLCOM|SoftBank|Semulator|Vemulator|J-EMULATOR|emobile|mixi-mobile-converter)) {
                set $mobile 1;
            }
            if ($http_user_agent ~* ‘(iPhone|iPod|Opera Mini|Android.*Mobile|NetFront|PSP|BlackBerry)) {
                set $mobile 2;
            }
            if ($http_cookie ~* “comment_author_[^=]*=([^%]+)%7C|wordpress_logged_in_[^=]*=([^%]+)%7C”) {
                set $do_not_cache 1;
            }
            proxy_no_cache     $do_not_cache;
            proxy_cache_bypass $do_not_cache;
            proxy_cache czone;
            proxy_cache_key “$scheme://$host$request_uri$is_args$args$mobile”;
            proxy_cache_valid  200 301 302 10m;
            proxy_cache_valid  404 5m;
            proxy_cache_use_stale  error timeout invalid_header updating
                                   http_500 http_502 http_503 http_504;
            proxy_pass http://backend;
            proxy_redirect http://example.com:8080/ /;
        }

        location ~ /purge(/.*) {
            allow 127.0.0.1;
            allow 192.0.2.1;
            deny all;
            proxy_cache_purge czone “$scheme://$host$1$is_args$args$mobile”;
        }
    }

    server {
        listen       8080;
        server_name  example.com;

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

        error_page  404              /404.html;
        location = /404.html {
            root   /usr/share/nginx/html;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }

        location ~ .php$ {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /var/www/html$fastcgi_script_name;
            include        fastcgi_params;
        }

        location ~ /.ht {
            deny  all;
        }
    }

    # Load config files from the /etc/nginx/conf.d directory
    include /etc/nginx/conf.d/*.conf;
}

この設定ファイルは以下のサーバ環境用に設定しています。サーバ環境に応じて適宜修正してください。

  • サーバの IP アドレス: 192.0.2.1
  • ホスト名: example.com
  • HTML ドキュメントルート: /var/www/html
  • リバースプロクシのポート: 80
  • バックエンドウェブサーバのポート: 8080
  • PHP FastCGI サーバのポート: 9000

ドキュメントルートに対して nginx ユーザーから読み込み権限が必要になります。WordPress を使用する場合ウェブディレクトリに対して書き込み権限も必要ですので、ドキュメントルートのオーナーを nginx ユーザー(FastCGI の実行ユーザー)に変更しておく方が良いかもしれません。


リバースプロクシのキャッシュを PC と携帯とスマートフォンで切り替える設定を入れています。不要な方は location / の設定を以下のように変更してください。Ktai StyleWPTouch を使う場合はそのままで。

        location / {
            proxy_no_cache     $do_not_cache;
            proxy_cache_bypass $do_not_cache;
            proxy_cache czone;
            proxy_cache_key “$scheme://$host$request_uri$is_args$args”;
            proxy_cache_valid  200 301 302 10m;
            proxy_cache_valid  404 5m;
            proxy_cache_use_stale  error timeout invalid_header updating
                                   http_500 http_502 http_503 http_504;
            proxy_pass http://backend;
            proxy_redirect http://example.com:8080/ /;
        }

設定ファイルを自分の環境用に書き換えたら nginx を動かします。

/etc/init.d/nginx start

この状態でブラウザからホストにアクセスすると 403 Forbidden が表示されると思います。

ドキュメントルートに空のファイルを作成し、ブラウザでアクセスできるか確認します。

cp /dev/null /var/www/html/index.html

同じく phpinfo を実行するスクリプトを作成し、ブラウザでアクセスできるか確認します。

echo ‘<?php phpinfo() ?>’ > /var/www/html/phpinfo.php

動作が確認できたら index.html と phpinfo.php を削除し(残してても良いですけど)、chkconfig を実行してリブート時に nginx と PHP FastCGI サーバが起動するように設定します。

/sbin/chkconfig –level 345 nginx on
/sbin/chkconfig –level 345 php-fastcgi on

WordPress のインストール

PHP の動作が確認できれば、WordPress のインストール自体は Apache の場合とそれほど違いません。

まず VPS ですので mysql コマンドでデータベースを作ります。

CREATE DATABASE wordpress DEFAULT charset utf8;
GRANT ALL ON wordpress.* TO ‘wpuser’@‘localhost’ IDENTIFIED BY ‘password’;

ja.wordpress.org から最新版の WordPress をダウンロードして /var/www/nginx に展開します。

cd /var/www/nginx
wget http://ja.wordpress.org/latest-ja.zip
unzip /tmp/latest-ja.zip
chown -R nginx:nginx wordpress

wordpress ディレクトリの wp-config-sample.php を wp-config.php にコピーし、

cd wordpress
cp wp-config-sample.php wp-config.php

wp-config.php にデータベース設定と FS_METHOD を追加します。FS_METHOD を direct にすると、WordPress プラグインなどのダウンロード時に ftp を使用せず PHP スクリプトから直接ダウンロードするようになります。必須ではありませんが、VPS で ftp の設定をわざわざするのも面倒なので付けてます。

define(‘DB_NAME’, ‘wordpress’);
define(‘DB_USER’, ‘wpuser’);
define(‘DB_PASSWORD’, ‘password’);
define(‘FS_METHOD’, ‘direct’);

WordPress の設定が終わったら、ブラウザでアクセスする前に、/wordpress/wp-admin へのアクセスをキャッシュしないよう nginx.conf のリバースプロクシの設定を変更します。(この修正を入れた nginx.conf を nginx-wordpress.conf に置いています。)

    server {
        listen       80;
        server_name  example.com;

        location /wordpress/wp-admin/ {
            proxy_pass http://backend;
        }

        location / {

nginx.conf を修正したらリブートします。

/etc/init.d/nginx restart

これでブラウザから http://example.com/wordpress/ などのインストールした URL にアクセスすると WordPress のインストーラが立ち上がります。


パーマリンクの変更

パーマリンクを /wordpress/archives/1 等の形式に変更する場合、WordPress の設定を変える前に nginx.conf のバックエンドサーバの設定を変更する必要があります。

WordPress のインストール先が /wordpress/ で、/wordpress/ 以下のみを WordPress として運用する場合(トップページを WordPress に割り当てない)は、以下のように nginx.conf の location / に if (!-f $request_filename) { } を加え、location /wordpress を加えます。

    server {
        listen       8080;
        server_name  example.com;

        location / {
            root   /var/www/nginx;
            index  index.html index.htm index.php;
            if (-f $request_filename) {
                break;
            }
        }

        location /wordpress {
            root   /var/www/nginx;
            index  index.html index.htm index.php;
            if (!-e $request_filename) {
                rewrite ^(.+)$  /wordpress/index.php?q=$1 last;
            }
        }

設定を変更したら nginx をリブートします。

/etc/init.d/nginx restart

nginx をリブートしたら WordPress のパーマリンク設定を変更します。


パーマリンクの変更(WordPress ディレクトリとは別のディレクトリにサイトのホームページを設定する場合)

なにを言ってるかよく分からないかもしれませんが、WordPress の一般設定で以下のキャプチャのように WordPress のアドレス (URL) とサイトのアドレス (URL) を変えた場合に、パーマリンクの変更を行うための設定方法です。

この設定を行う場合、まず wordpress/index.php をコピーして HTML ドキュメントルートに index.php を作ります。

cd /var/www/html
cp wordprses/index.php index.php

コピーした index.php の require 部分を以下のように書き換えます。

require(‘./wordpress/wp-blog-header.php’);

nginx.conf のバックエンドサーバの設定を書き換えてから、nginx をリブートします。

    server {
        listen       8080;
        server_name  example.com;

        location / {
            root   /var/www/nginx;
            index  index.html index.htm index.php;
            if (-f $request_filename) {
                break;
            }
            if (!-e $request_filename) {
                rewrite ^(.+)$  /index.php?q=$1 last;
            }
        }

nginx をリブートが完了したら WordPress のパーマリンク設定を変更してください。

Nginx Proxy Cache Purge WordPress プラグインのインストール

WordPress のインスコが終わったら Nginx Proxy Cache Purge WordPress プラグインを入れます。普通に WordPress のダッシュボードからインスコしてください。

このプラグインを入れると、記事を更新した際に nginx のキャッシュがパルスのファルシのルシがパージされるようになります。このプラグインを入れないと nginx のキャッシュタイムアウトまでの間(上の設定だと10分)古い内容で表示されることになりますので、nginx でリバースプロクシ立てたサイトで WordPress を動かすときは一緒にインスコしておいた方が良いです。

ちなみにこのプラグイン、パージ URL が /purge/* 固定(上の nginx の設定はこれに合わせています)でソースコード中にハードコーディングされていますので、パージ URLを変更したい場合はプラグインのソースを書き換える必要があります。上の nginx の設定例ではパージ URL を /purge にしてますので書き換えなくても問題ありませんが、変更したい場合はちょっと不便かもです。

nginx purge とかで WordPress プラグインを検索すると、他にも nginx のキャッシュをパージするためのエナがチャンガしてるプラグインが何個かありますので、他に良さげなのがあればそちらをどうぞ。

ちなみに、リバースプロクシでキャッシュしている場合は WP Super Cache 等のキャッシュプラグインは要りませんので、他のサイトから移行してきた場合キャッシュ関係のプラグインは無効または削除した方が良いと思います。

ベンチマーク

画竜点睛を欠くふいんき(なぜかry)でしたので、さくら VPS 512 上で httperf でWordPress のベンチマークを取ってみました。ついでにさくらスタンダードの WordPress に対してもベンチマークを取っていますが、こちらはサーバ環境が違いすぎるのであくまでも参考値ということで。

VPS の Apache はほぼデフォルトの設定/VPS の nginx はリバースプロクシありの設定ですので、ぶっちゃけフェアな比較ではありませんがまあこんなもんだと思います。(Apache の mod_cache を有効にするとか性能的な対策が可能ですが、別の VPS 鯖で mod_cache 入れたら過負荷になったときにサーバが落ちた(入れる前は過負荷でも落ちなかった)のでピーク時性能についてはどっちもどっちだと思います。まあ細かいことを言い出したらキリが無いので別の条件でベンチ取りたい人はよろしく〜(^o^)/)


まず最初のグラフは1秒あたりのサーバが返したレスポンス数です。

グラフのY軸がレスポンス数/秒、X軸が1秒あたりにクライアントから同時に発生したリクエスト数です。

nginx が nginx の WordPress トップページに対するベンチマーク、apache(VPS) が VPS 上で動かした Apache の WordPress トップページに対するベンチマーク、apache(STD) がさくらスタンダード上(の Apache)で動かした WordPress トップページに対するベンチマークの値です。

一個だけ見てもよく分からない部分が多々ありますので先にグラフを全部貼ります。


次のグラフは正常に完了したリクエストのレスポンスタイム(ミリ秒)です。

同時リクエスト数 70 〜 80 の間で Apache (VPS) のレスポンスタイムが 0 になっているのは、次のグラフのとおりサーバが落ちていたためです。


最後のグラフはエラーが返された数です。

Apache (VPS) では、リクエスト数(X軸)が70と80の時にエラーが70と80返されています。ベンチマークのリクエストが50を越えたあたりからサーバが処理しきれなくなって、70 〜 80 の間完全に落ちた状態となり、(このベンチマークは連続して行いましたので)90ぐらいから先に送ったリクエストが(タイムアウトなどで)終了し始め、100リクエストのころにはちょっと回復していた感じになっています。

Apache (STD) が微妙にエラーを出してるのは、アクセス制御用のモジュールを入れているからだと思いますが、自分で設定したサーバでは無いので詳細は不明です。


以上から、

  • nginx: 25 〜 44 リクエスト/秒のスループットで、同時リクエスト数が 60 を越えたあたりからレスポンスタイムが悪化(最高値 720.2 ms)、同時リクエスト数が 90 を越えたあたりからエラーが出始める。
  • Apache (VPS): 13 〜 24 リクエスト/秒のスループットで、同時リクエスト数が 20 を越えたあたりからレスポンスタイムが悪化(最高値 3643.2 ms)、同時リクエスト数が 50 を越えたあたりからエラーが出始め、一時完全に落ちた。
  • Apache (STD): 18 〜 30 リクエスト/秒のスループットで、レスポンスタイムは線形に悪化していないので詳細不明、割とすぐにエラーを返し始める。共有サーバだし詳細もよく分からんのでご勘弁を。

みたいな感じだと思います。

とりあえず VPS で WordPress を動かすなら nginx 使う方が良い(*´・ω・)(・ω・`*)ネー、って結果でした。

VPS についてはベンチマーク中に Load Average も計ってたんですが、nginx の最高値が 0.14、Apache の最高値が 132.56 でした。お話にならんって感じです。

VPS サーバで一番メモリを使ってるのは MySQL サーバですので、ここをチューニングするとさらに速くできるかも、です。
nginx のキャッシュに memcached を使ったりもできるのですが、さくら VPS 512 にデータベースやらなんやら全部置いててメモリ的に厳しいので今のところパスしてます。

こちらの記事によると別の VPS に DB サーバを立てたりしてもおkみたいですので、チューニングの余地は結構ある感じです。
さくらクラウドで動かすのもいいかもしれませんねー。


てことで、WordPress が重い重い言ってる人は nginx に乗り換えチャイナYOU!

参考サイト

最後に sakuratan.biz を nginx に移行する際に参考にしたページのリンクを貼っときます。この記事のとおり作業してみたけど何かうまくいかないって時は以下のサイトに解決方法があると思います。

apache の脆弱性

先日、apacheの脆弱性が公開された。この脆弱性は、既存の全バージョンで確認され、「緊急」扱いとなっている。

今回は、この脆弱性が如何に危険な存在であるか、検証してみよう。

今回見つかった脆弱性は、と呼ばれるもので、ざっくりと言ってしまえば、サービス拒否攻撃の類だ。サービス拒否攻撃には、いくつかの手法があり、

  1. 帯域圧迫型
  2. socket飽和型
  3. CPU占有型
  4. メモリ圧迫型

の4種類に大別することが出来る。このうち、1は一般的にはDDoS攻撃と呼ばれるもので、古くは「田代砲」と呼ばれる攻撃ツールもあった。2は、1と似ているが、大した帯域を使わず、大量にセッションを張るだけ張り、持続させて、相手のsocketを食いつぶす。syn floodやack flood攻撃もこの種になる。

3は、CGIを呼び出す部分のみを、高速に外部から呼び出し、CGIに費やす負荷を極限まで上げる方法だ。4は、ファイル転送を行う際に、大量かつ大容量のデータを転送することで、内部メモリを飽和させる方法だ。

今回見つかった脆弱性は、3と4を合わせ持つ強力なものだ。通常3や4を実行する場合、攻撃側もそれ相応の機材やネットワークを必要とし、botネットを用いることが一般的だ。しかし、今回の脆弱性を検証するために用いられたツールは、わずか8000バイト弱のデータを、1つのhttpリクエストにしたため、接続しているだけだ。

通信内容は、次のようになっている

HEAD / HTTP/1.1

Host: 192.168.2.113

Range:bytes=0-,5-0,5-1,5-2,5-3,5-4,5-5,5-6,5-7,5-8,5-9,5-10,5-11,5-12,5-13,5-14,5-15,5-16,5-17,5-18,5-19,5-20,5-21,5-22,5-23,5-24,5-25,5-26,5-27,5-28,5-29,5-30,5-31,5-32,5-33,5-34,5-35,5-36,5-37,5-38,5-39,5-40,5-41,5-42,5-43,5-44,5-45,5-46,5-47,5-48,5-49,5-50,5-51,5-52,5-53,5-54,5-55,5-56,5-57,5-58,5-59,5-60,5-61,5-62,5-63,5-64,5-65,5-66,5-67,5-68,5-69,5-70,5-71,5-72,5-73,5-74,5-75,5-76,5-77,5-78,5-79,5-80,5-81,5-82,5-83,5-84,5-85,5-86,5-87,5-88,5-89,5-90,5-91,5-92,5-93,5-94,5-95,5-96,5-97,5-98,5-99,5-100,5-101,5-102,5-103,5-104,5-105,5-106,5-107,5-108,5-109,5-110,5-111,5-112,5-113,5-114,5-115,5-116,5-117,5-118,5-119,5-120,5-121,5-122,5-123,5-124,5-125,5-126,5-127,5-128,5-129,5-130,5-131,5-132,5-133,5-134,5-135,5-136,5-137,5-138,5-139,5-140,5-141,5-142,5-143,5-144,5-145,5-146,5-147,5-148,5-149,5-150,5-151,5-152,5-153,5-154,5-155,5-156,5-157,5-158,5-159,5-160,5-161,5-162,5-163,5-164,5-165,5-166,5-167,5-168,5-169,5-170,5-171,5-172 以下略

こう言った攻撃コードを、1回の通信で行っている。

ここで注目すべきは、「Range:bytes=」だ。

このRangeは、データを分割する際に用いる方法

だ。つまり、大量のデータがある場合、そのデータをいくつかに分割し、転送することを要求している。5-6 5-7 と言ったように、特定のバイトからバイトまでを分割して転送要求を行う。5-0 バイトから5-1299バイトまでを、1バイトづつ増やしながら、同じものを含め、再度転送することを要求する。この要求を受けたターゲットは、その要求に従い、律儀に転送しようと試みる。

これを受け取ったサーバは、下記に示すように、要求された分だけ、apacheの接続を受け止めようとする。

https://i0.wp.com/doruby.kbmj.com/totoro_blog/files/kill+apache+%E6%A4%9C%E8%A8%BC%E7%92%B0%E5%A2%83.png

見てわかるように、この時点でload average は、40を越えている。通常のサーバではありえない現象だ。

この時の通信ログは

192.168.3.26 – – [01/Sep/2011:10:20:37 +0900] “HEAD / HTTP/1.1” 206 354 “-” “-“

192.168.3.26 – – [01/Sep/2011:10:20:37 +0900] “HEAD / HTTP/1.1” 206 354 “-” “-“

192.168.3.26 – – [01/Sep/2011:10:20:37 +0900] “HEAD / HTTP/1.1” 206 354 “-” “-“

192.168.3.26 – – [01/Sep/2011:10:20:37 +0900] “HEAD / HTTP/1.1” 206 354 “-” “-“

192.168.3.26 – – [01/Sep/2011:10:20:37 +0900] “HEAD / HTTP/1.1” 206 354 “-” “-“

192.168.3.26 – – [01/Sep/2011:10:20:37 +0900] “HEAD / HTTP/1.1” 206 354 “-” “-“

192.168.3.26 – – [01/Sep/2011:10:20:37 +0900] “HEAD / HTTP/1.1” 206 354 “-” “-“

192.168.3.26 – – [01/Sep/2011:10:20:37 +0900] “HEAD / HTTP/1.1” 206 354 “-” “-“

192.168.3.26 – – [01/Sep/2011:10:20:37 +0900] “HEAD / HTTP/1.1” 206 354 “-” “-“

となっており、先程の様な、Range:bytes=は含まれていない。

この状況が続くとどうなるのか、状況を見てみよう。

https://i0.wp.com/doruby.kbmj.com/totoro_blog/files/wa97.png

waが97%を示していることがわかるだろうか。これは、IO Wait と呼ばれるもので、通信ではなくIO系の処理にそれだけのwaitが発生していることを示す。

この数値が大きければ、大きいほどシステムの反応速度は落ち、ファイルの書き込みや様々な応答速度は悪くなる。

webブラウザで接続した際、クルクルとレインボウカーソルが発生し、何時まで経っても、画面が表示されない。そういった状況を想い出せばよいだろう。

この状況が続くと、メモリもCPUも圧迫され続け、システムそのものへのssh接続もままならなくなる。

こうなると、システムは次の画面にあるように、OOM Killer を発動する。

https://i0.wp.com/doruby.kbmj.com/totoro_blog/files/oom_killer.png

この状況では、諸悪の根源を、apache に有ると考え、apache のタスクを殺しにかかる。

この時、apacheの抱えるタスクは当然のごとく消され、最悪の場合システムが完全にロックする場合もある。

この記事を書いてる現在、既にapache 2.2.20のパッチが提供され、それ以外のバージョンでも暫定的な対応策が公開されている。まだ、apacheの対策を行っていないのであれば、早急な対応されることの望む。最悪の場合、apacheどころか、OSまで止まるのだから。

そろそろApacheからNginxに移行したい人の、Nginx スターティング・ガイド

AV女優.com は7月1日に、 Apache から Nginx にウェブサーバを切り替えました。
理由は簡単で、少しでもパフォーマンスを上げるためです。
あまり収益も上がっていないので ( 先月の収益報告 ) 、サーバ費用を捻出出来ません。

今日は、私が ApacheからNginxにウェブサーバを移行するために、掻き集めた情報 をまとめていきます。

Nginxに移行すべき理由

Nginxはパフォーマンスが良い と言われています。

しかし、本当にパフォーマンス良いのか?
また、本当にApacheからNginxに切り替えて、問題がないのか?

blog@a2o.siApacheBenchを使ったベンチマーク が分かりやすくまとまっています。

Apache + mod_php compared to Nginx + php-fpm
NginxでPHPを走らせる場合のバックエンドサーバとなるphp-fpmとApacheのmod_phpや、静的ファイルの処理性能を比較しています。
静的ファイルに関しても、 13バイト/100kバイト/1Mバイトの3種類のファイルサイズ で比較しています。

ここで分かる結果は、

  • PHPの処理性能は、 Nginx + php-fpmがApache + mod_rewriteに劣る
  • 静的ファイルの処理性能は、 ApacheよりもNginxのほうが圧倒的に高い

ということです。
PHPの処理性能に関して、この記事では、 サーバに余分なプロセス(php-fpm)が増えるんだから、Nginxのほうが遅くて当たり前だよね とまとめられています。

また、最終的な判断基準として、以下の6点を考えるべきだと言っています。

  1. たくさんの.htaccessファイル か、あるいは、 たくさんのApacheサーバ を所有しているのなら、Nginxに移行するべきではないでしょう。これらの設定ファイルを全て、Nginx形式に書き換えるコストよりも、新しいサーバを買うコストの方が安いでしょうね。
  2. もし、単体のアプリケーションを複数のサーバで配信していて、しかも、 その大半が静的ファイルでない場合 、Nginxに移行するべきではないでしょう。
  3. 逆に、 配信するファイルの大半が、静的ファイルである場合 、Nginxに移行するべきでしょう。
  4. 新たなウェブホスティングサービスを立ち上げる場合、Nginxに移行するべきでしょう。ただし、利用するユーザが .htaccessを必要としない場合に
  5. 仮想サーバ上でウェブサービスを運用する場合 、Nginxに移行するべきでしょう。Nginxが利用するメモリが、Apacheよりも少ないためです。
  6. もし、PHPアプリケーションのパフォーマンスが悪いために、Nginxの切り替えを考えているなら、ウェブサーバでなく、まずは アプリケーション自体を見直しましょう

当たり前といえば、当たり前ですが、最後の基準が大事ですね。
Nginxは高速化のための、 銀の弾丸 ではないということです。

移行する理由はパフォーマンスだけでしょうか?
Apacheと比べた場合の、Ngixの優位性として、そのシンプルな 設定ファイル が上げられます。
私が始めに感動したのは、 NginxHttpRewriteModule (Apacheのmod_rewrite) です。

HttpRewriteModule
HttpRewriteModuleの公式ドキュメントです。
条件を指定するディレクティブが、 if文 になっており、直感的です。
Apache Module mod_rewrite
Apacheのmod_rewriteモジュールの公式ドキュメントです。
ドキュメント自体もNginxのHttpRewriteModuleと比べて長く、わかりにくいです。

例えば、ユーザエージェントを判定する場合、Apacheの設定ファイルは次のようになります:

RewriteEngine OnRewriteCond %{HTTP_USER_AGENT} Android  [NC,OR]RewriteCond %{HTTP_USER_AGENT} iPod     [NC,OR]RewriteCond %{HTTP_USER_AGENT} iPhone   [NC]RewriteRule ^(.*)$ /m/$1 [L]

Nginxの場合は次のようになります:

if ($http_user_agent ~* Android|iPod|iPhone) {    rewrite (.*) /m$1;}

設定の意図がわかりやすいのは、Nginxです。
Apacheの場合、RewriteCondやRewriteRuleの意味と挙動を完全に知っている必要があります。
しかし、Nginxの場合、if文で書かれているため、 それとなく意味が分かります

是非、Nginxの設定ファイルを覗いてみてください。
きっと、惚れてしまいます。

NginxにApacheから移行するか否かは、 始めに紹介したブログの基準 を参考にすると良いでしょう。

AV女優.com には、ページ数が7,000弱あります。
これらの8割のページを、静的キャッシュしていることから、Nginxに切り替えました。
また、画像数も多いことも、決め手の一つでした。

PHPとPythonを走らせる

NginxでPHPやPythonを走らせるためには、Apacheと異なり、 バックエンドサーバ が必要です。
PHPであれば php-fpm が、Pythonであれば uWSGI が、これにあたります。

/img/posts/008/nginx_with_php-fpm_or_uwsgi.png

また、 Apache をバックエンドサーバとして、以下の構成を取ることも出来ます。

/img/posts/008/nginx_with_apache.png

つまり、今まで通りApacheは走らせておいて、Nginxにリクエストを処理させる方法ですね。
このための設定は、このページが参考になります。

Configuring Apache and Nginx
Apacheをバックエンドサーバとして走らせるための設定がステップ・バイ・ステップでまとまっています。

php-fpmでもuWSGIでも、Apacheでも、バックエンドサーバが異なるだけで、 全て同じ構成 です。
Nginxは、 静的ファイル だけ配信し、動的ページへのリクエストは、バックエンドサーバに丸投げします。

UbuntuにNginxをインストールする

実際にNginxをインストールします。
ここでは、パッケージが公式に用意されており、インストールがとても楽な Ubuntu を使います。

Nginx/php-fpm/uWSGIは全て LaunchPad にリポジトリがあります。

Nginx
Nginxの公式リポジトリです。最新のNginxが簡単にインストール出来ます。
php-fpm
Nginxが管理しているphp-fpmのリポジトリです。php-fpmが組み込まれた、PHP5.3が簡単にインストール出来ます。
uWSGI
uWSGIのリポジトリです。恐らく公式ではありませんが、uWSGI v0.9.6をインストール出来ます。

まずは、 Nginx をインストールします:

$ sudo apt-get install -y python-software-properties$ sudo add-apt-repository ppa:nginx/stable$ sudo apt-get update$ sudo apt-get install -y nginx

次に、 php-fpm をインストールします:

$ sudo add-apt-repository ppa:nginx/php5$ apt-get update$ apt-get install -y php5-fpm

最後に、 uWSGI をインストールします:

$ add-apt-repository ppa:uwsgi/release$ apt-get update$ apt-get install -y uwsgi-python

インストールはこれだけです。
簡単ですね。

続いて設定です。
まずは、 PHP を動かしてみます。
以下のファイルを /etc/nginx/sites-available/php-default に設置します:

server {    # 8080ポートで待ち受ける。    listen      8080;    server_name localhost;    # 静的ファイルは/var/www/php-default以下に配置する。    root  /var/www/php-default;    index index.html index.htm;    access_log /var/log/nginx/php-default.access.log;    error_log  /var/log/nginx/php-default.error.log;    # PHPスクリプトは、9000ポートで待ち受けているphp-fpmに問い合わせる。    location ~ .php$ {        include       fastcgi_params;        fastcgi_pass  127.0.0.1:9000;        fastcgi_index index.php;        fastcgi_param SCRIPT_FILENAME /var/www/php-default$fastcgi_script_name;        fastcgi_intercept_errors on;    }}

設定を有効にし、 Nginxphp-fpm を起動します:

$ sudo ln -s /etc/nginx/sites-available/php-default /etc/nginx/sites-enabled$ sudo /etc/init.d/nginx start$ sudo /etc/init.d/php5-fpm start

サーバの8080ポートにアクセスすると、設置したPHPスクリプトの結果が表示されるはずです。

続いて、 Python を動かしてみます(ここではマイクロフレームワークflaskを動かします)。

始めに uWSGI を設定します。
以下のファイルを /etc/uwsgi-python/apps-available/app.xml に設置します:

<uwsgi>    <socket>127.0.0.1:9001</socket>    <env>FLASK_ENV=development</env>    <pythonpath>/srv/flask</pythonpath>    <module>app</module>    <callable>app</callable></uwsgi>

次に、 Nginx を設定します。
以下のファイルを /etc/nginx/sites-available/python-default に設置します:

server {    # 8090ポートで待ち受ける。    listen       8090;    server_name  localhost;    # 静的ファイルは/var/www/python-default以下に配置する。    root   /var/www/python-default;    index  index.html index.htm;    access_log  /var/log/nginx/python-default.access.log;    error_log   /var/log/nginx/python-default.error.log;    # uWSGIがページを提供出来るか、問い合わせる。    # 提供出来ない場合、/var/www/python-defaultから、静的ファイルを配信する。    location / {        try_files $uri @uwsgi;    }    # 静的ファイル以外は、9001ポートで待ち受けているuWSGIに問い合わせる。    location / {        include     uwsgi_params;        uwsgi_pass  127.0.0.1:9001;    }}

設定を有効にし、 uWSGI を起動します:

$ sudo ln -s /etc/nginx/sites-available/python-default /etc/nginx/sites-enabled$ sudo /etc/init.d/nginx reload$ sudo /etc/init.d/uwsgi-python start

サーバの8090ポートにアクセスすると、設置したPythonスクリプトの結果が表示されるはずです。

動かすための最小限の設定はこんなところです。
その他の設定は次にまとめたサイトを参考に、調整してください。

参考になる各種設定

以下にNginxを設定する際に 参考になる記事 をまとめます。

設定に関するTIPS

Nginx Pitfalls
公式ドキュメントの設定例です。一度、目を通しておきましょう。
悪い設定例と良い設定例を比較しながらの説明です。
nginxでメンテナンス中画面を表示する
Nginxで メンテナンスページ を表示するための設定です。
エラーページをディレクティブを使って、あっさりと設定出来ます。
nginxのHttpLimitReqModuleを試してみる
Web APIを公開すると必要となる、 アクセス制限 をNginxの標準モジュールで設定しています。
1秒間に1回のリクエストを許可する、といったことを簡単に設定出来ます。
RapidSSL 発行の SSL 証明書を Nginx で使う
NginxとApacheのSSL設定は若干、異なります。
RapidSSLを例に、Nginxの SSL設定 が解説されています。
Serving an iPhone website with nginx
Nginxで iPhoneサイト を運用するための設定集です。
ユーザエージェントはもちろんんこと、Cookieを使った振り分けから、様々な設定が解説されています。

環境構築

nginx+php-fpmをyumでインストールして、WordPress/CakePHPを動かす設定
WordPressCakePHP をNginxで動かすための設定です。
ステップ・バイ・ステップでわかりやすく書かれており、参考になります。
Nginx Logwatch Configuration
Nginxをサーバ監視ツール logwatch に対応させるための設定です。
ログはApacheと同じCombined形式であるため、簡単に対応させることが出来ます。

パフォーマンスチューニング

Optimize Nginx + PHP-FPM for faster response times (for Openx adserving)
StackOverflowで投稿された パフォーマンスチューニング に関する質問です。
Nginxのパフォーマンスチューニングの基本がわかります。
How-to: NGINX efficiency tricks
こちらも パフォーマンスチューニング の参考になります。
効果的な設定が6つ紹介されています。

全般

ハイパフォーマンスHTTPサーバ Nginx入門
日本語で書かれた唯一の書籍です。
私はまだ読んでいませんが、 サーバスペック別に書かれた設定サンプル が参考になりそうです。

Nginxの簡単な設定と、参考になる記事をまとめました。
他にも、有用な情報があればコメント欄までお願いします。
追記させて頂きます。

DTI VPSの大部分がオープンプロキシになっていた件について – Magical Diary

Twitterで断片的につぶやいた (http://twilog.org/hirayasu/date-101230) 内容をもう少し詳しくまとめておく。

概要

先日、DTIのServersMan@VPS*1メンテナンス (機能追加) http://www.dti.co.jp/release/101216.html でAirDisplay@VPS*2インストールが行われたが、設定ミスがありほぼ全てのVPSオープンプロキシ (アクセス制限が行われず誰でも利用出来るプロキシサーバ) となっている状態だった。

12/27メンテナンス作業後

まず、27日のメンテナンス時点で /etc/httpd/conf.d/proxy_ajaxterm.conf にはイカのように記載されていた。これは localhost:8022 で動作する AjaxTerm に対するリバースプロキシ設定だが、本来不要な記載をしているためにセキュリティ上の問題があった。

<IfModule mod_proxy.c>ProxyRequests On<Proxy *>        Order deny,allow        Deny from all        Allow from all</Proxy>ProxyPass /airdisplay/ http://localhost:8022/ProxyPassReverse /airdisplay/ http://localhost:8022/

ProxyRequests On を設定することによりApacheHTTP Proxyサーバとして動作するが、ProxyPass, ProxyPassReverse を利用する場合にはこの設定を有効にする必要は全く無い。これは、Apacheマニュアルにもイカのように記載されている。

The ProxyRequests directive should usually be set off when using ProxyPass. (http://httpd.apache.org/docs/2.2/en/mod/mod_proxy.html#proxypass)

さらに、このプロキシ機能に対して Allow from all (制限無しにアクセス可能) を設定したため、無制限にプロキシ機能を提供するオープンプロキシの状態となっていた。

12/30緊急メンテナンス作業後

ProxyRequests On の設定は12月30日の緊急メンテナンスコメントアウトされたようだがProxy * に対するアクセス制限が allow from all のままとなっているため、元々HTTP Proxyサーバとして動作させている場合にはそのアクセス制限にかかわらず、allow from allで上書きされる可能性がある。

ServersMan@VPSサービス 緊急メンテナンスのお知らせ

http://info.dti.ne.jp/announce/docs/20101230_01.html

CentOS/RHELパッケージで導入されたApache場合、/etc/httpd/conf/httpd.conf に

include conf.d/*.conf

という記載があり、途中で設定が読み込まれる。この読み込まれる順番は文字コード順となる。

proxy_ajaxterm.conf が読み込まれる前にHTTP Proxyの設定が記載されていた場合、たとえば192.0.2.0/24 からのみアクセス可能とするためにproxy.confというファイル名 (読み込み順はproxy_ajaxterm.confより先となる) で以下の設定を行っている場合でも、アクセス制限は上書きされてオープンプロキシとなる。

ProxyRequests On<Proxy *>  Order deny,allow  deny from all  allow from 192.0.2.0/24</Proxy>

HTTP Proxyサーバとして利用している例は多くはないだろうが、メンテナンスでは既存環境に極力影響を与えないように行うべきだと思う。

推奨する設定変更

AjaxTermを無効化、AjaxTermに対するリバースプロキシ設定を削除することをおすすめする。

service ajaxterm stopchkconfig ajaxterm offrm /etc/httpd/conf.d/proxy_ajaxterm.confservice httpd restart

また、各種ブラックリストに登録されていないか確認しておく方が良いだろう。

yebo blog: Wikipediaサーバの実態

関西オープンフォーラム「KOF2010」で、Wikipedia財団のエンジニアRyan Lane氏がWikipedia/MediaWikiのサーバ運用の実態を発表したそうだ[gigazine]。世界の上位5番目のサイトであるWikipediaのサーバは350台しかないのに驚くが、運営者も6名と非常に少ないのに更に驚く(ボランティアも含まれる)。WikipediaのサーバアーキテクチャはLAMP(Linux、Apache、MySQL、PHP)であり、Memcachedによって高速化している。その他、Squid (Vernish cacheに移行予定)、CARPLVSPowerDNS(CDN用DNS)などのオープンソースが駆使されているとのこと。

yebo blog: GoogleがApacheを高速化するモジュールを公開

GoogleがApacheを高速化するモジュールを公開

Googleが、Apache Webサーバを高速化するモジュール「mod_pagespeed」(Page SpeedのApacheもジュール版)を公開した。このモッジュールをインストールするだけで、キャッシュの最適化、ペイロードサイズの最小化、クライアントとサーバ間のラウンドトリップ時間の最小化など15以上の最適化を自動で行う。Googleによれば、mod_pagespeedを利用すると、Webページのロード時間を50%短縮でき、サイトの応答速度は倍に改善するという。