December 25, 2010

最速最安WEB画像サーバ構築術 - nginx + ServersManAdd Starshimookagothedistancekitayamakitayama

15:59 | 最速最安WEB画像サーバ構築術 - nginx + ServersMan - 新・浅く広くをモットーに | 一人WEBサービス屋メモ を含むブックマーク

先日、運営しているサイトcocoの画像サーバを構築しました。昨今はVPSが500円程度で借りられる様になり、一人WEBサービス屋には本当にいい時代になりました。今回、選定対象にしたのは、以下3つの業者です。

料金やスペックについて、2010/12/19時点のものを記載しました。キャンペーン適用や保障スペックなど細かい注意点がありますので、詳しくは各社サイトでご確認下さい。

シミュレーション

処理数値目標は、月間1億アクセスとしました。これは、1ページ当たり50画像掲載だったとすると、200万PV。ブラウザキャッシュやCSS Spliteの導入を考えると、もっと多くのPVに絶えられると言えるでしょう。月間の数値が決まったら、後は秒間アクセスを出すだけです。

1億 / 30日 / 24時間 / 60分 / 60秒 ≒ 39(per/sec)

更に、アクセスは1日を通して平均的である事は稀ですので、ピークタイムを平均の倍にすると「79(per/sec)」。今回はこれを目標数値とします。

Apache

まずは、使い慣れたApache(2.2.17)をインストールしてみました。Apacheは、標準モジュールによるオーバヘッドが大きいので、画像サーバに必要なモジュールのみとしました。以下、コンパイルオプション

./configure --prefix=/usr/local/apache --with-mpm=worker --disable-option-checking --disable-FEATURE --disable-authn-file --disable-authn-default --disable-authz-host --disable-authz-groupfile --disable-authz-user --disable-authz-default --disable-auth-basic --disable-include --disable-filter --disable-charset-lite --disable-env --disable-setenvif --disable-version --disable-status --disable-autoindex --disable-asis --disable-cgid --disable-cgi --disable-negotiation --disable-dir --disable-actions --disable-userdir --disable-alias --disable-log-config

上記は「—disable-mime」以外の全標準モジュールを排除しています。Disk I/O軽減の為、アクセスログも吐きません(エラーログは、この設定で吐き出します)。Apacheの標準モジュールは、

./configure --help | grep disable

で確認できますので、viなりで必要な箇所を抽出すれば、簡単に「configure」オプションが作れます。後は一本道でインストールです。

$ make
$ su
# make install

httpd.conf は必要なもののみ書くようにしています。

Listen 80
ServerName example.com
ServerRoot /usr/local/apache
DocumentRoot /var/www/htdocs

User nobody
Group nobody

ServerLimit 2
StartServers 2
MaxClients 32
MinSpareThreads 2
MaxSpareThreads 2
ThreadsPerChild 16
KeepAlive off

<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>

パフォーマンスに影響するポイントは、以下の通りです。

  1. SymLinkを許可する(許可しないとアクセス毎に通常ファイルかシンボリックリンクかの判断が入ってしまいます)
  2. AllowOverrideを無効(上に同じくアクセス毎に.htaccessらが使えるかの判断が入ってしまいます)
  3. KeepAliveはOff

何故、KeepAlive Offを推奨するかは、拙作「間違いだらけのWEBサーバ Keep-Alive」を御参照下さい。その他、MaxClients等のパラメータの説明は基本ですので省略します(と言いますか、この説明は無駄になる事がすぐ後で分かります)。

「さあ、モジュールも減量したし、まだまだApacheも現役でいけるでしょう」と思って、ベンチマークを取ってみたのですが。。。「allocate」エラー頻発。「おかしいなあ」と思って、Apacheを再起動しメモリ解放後、メモリ使用量を確認。

$ free -m
【Apache 起動前】
             total       used       free     shared    buffers     cached
Mem:           512         19        492          0          0          0
-/+ buffers/cache:         19        492
Swap:            0          0          0

【Apache 起動後】
             total       used       free     shared    buffers     cached
Mem:           512        202        309          0          0          0
-/+ buffers/cache:        202        309
Swap:            0          0          0

プロセスを起動しただけでメモリ使用量がこんなに。そう。メモリが足りなかったのです。前述httpd.confのスレッド数が極端に少ないのも、実はメモリ使用率の切り分けの為に徐々に少なくしていったからなのでした。

nginx

256Mメモリ環境(ServersManの場合、256M保証/最大512M)においては、Apacheでは埒があかない事が分かりました。今度は、nginxをインストールしました(初体験)。

$ wget "http://www.nginx.org/download/nginx-0.8.53.tar.gz"
$ tar zxvf nginx-0.8.53.tar.gz
$ cd nginx-0.8.53
$ ./configure --prefix=/usr/local/nginx --without-pcre --without-http_rewrite_module --without-http-cache --without-http_gzip_module
$ make
$ su
# make install

nginx.conf は、以下の通りです。

user  nobody nobody;
worker_processes  5;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    log_format  null  '';
    access_log  /dev/null  null;
    sendfile        on;
    keepalive_timeout  0;
    server_tokens  off;
    server {
        listen       80;
        server_name  localhost;
        root /var/www/htdocs;
        location / {
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

KeepAlive Off(keepalive_timeout 0;)と、アクセスログを吐かない様(access_log /dev/null null;)にしたぐらいで後は基本的な設定となっています。Apache同様、不要な機能を削除しようとマニュアルを熟読しようとも思ったのですが、まずは動かす事を優先しました。起動コマンドは以下。

# /usr/local/nginx/sbin/nginx

nginx 起動設定

起動スクリプトは簡単に以下の様なものにしました。

#!/bin/bash
#
# Startup script for the nginx
#
# chkconfig: 345 80 15
# description: Nginx web server.

# Source function library.
. /etc/rc.d/init.d/functions

start(){
    /usr/local/nginx/sbin/nginx
}

stop(){
    kill `cat /usr/local/nginx/logs/nginx.pid`
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        sleep 1
        start
        ;;
    *)
        echo "Usage: $0 {start|stop|restart}"
esac

exit 0

後はLinuxの基本操作です。自動起動設定をした上で、OSを再起動し動作確認をします。

# chkconfig --add nginx
# chkconfig nginx on
# chkconfig --list | grep nginx
# shutdown -r now

ベンチマーク

ベンチマークは、abを利用し、各VPSサーバ業者間のネットワーク経由で実行しました(正常アクセス程度に留めました。恐縮です!逮捕しないで下さい。)。

$ /usr/local/apache2/bin/ab -c 100 -n 1000 "http://example.com/logo.gif"

各社の数値の公開は差し控えますが、今回は、検証結果と料金・スペックなどの要素を元に総合判断し「ServersMan」を採用する事にしました。以下、ServersManでのabの結果参考値です。

Document Length:        3698 bytes
Requests per second:    242.68 [#/sec] (mean)

「79(per/sec)」は軽くオーバーしています。 abでの負荷テスト中に、ブラウザでアクセスしても問題がない事も確認しました(ちなみに、ローカルホスト内でのabでは、Requests per second: 5811.32 [#/sec]といった具合)。

また、CPU/メモリ使用率共にほぼ未使用といった感じです。

$ free -m
             total       used       free     shared    buffers     cached
Mem:           512         23        488          0          0          0
-/+ buffers/cache:         23        488
Swap:            0          0          0

$ top -d1
Cpu(s):  1.0%us,  1.0%sy,  0.0%ni, 98.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st

nginxは凄いですね。細かいチューニングも考える必要がありません。

最後に

後は、ネットワーク帯域や各社のF/Wなりの同時接続数制限をクリアしなければならない訳ですが、この辺りは、運用しながらレスポンス遅延が発生した段階で、VPS各社に増設&分散をさせていけばいいと思います(ちなみに、1億アクセスを目標数値にしましたが、そもそもこの規模のアクセスを発生させるWEBサービスを作る事が一番大変です^^;)。

それでは次回は、nginxでの画像サーバの構成案を含めた具体的な構築術を御紹介したいと思います。