オープンソースの HAProxy とNginx を組み合わせてコンテンツキャッシュシステムを構築するメモの続きです。
既存の環境にも後付けできるようなコンテンツキャッシュシステムを作るという事で、前回は HAProxy について書きましたが今回は Nginx の部分について。
Nginx でリバースプロキシとキャッシュを構成して、HAProxy と繋げるまでやってみたいと思います。
スポンサーリンク
Nginx の構成例
Nginx は version 1.4.7 を使ってリバースプロキシ + キャッシュを構成してみます。
下記は FreeBSD の Ports からインストールしたものですが、こんな感じのオプションを指定してインストールしてます。cache purge モジュールはぶっちゃけお好みで構いません。
# nginx -V nginx version: nginx/1.4.7 TLS SNI support enabled configure arguments: --prefix=/usr/local/etc/nginx --with-cc-opt='-I /usr/local/include' --with-ld-opt='-L /usr/local/lib' --conf-path=/usr/local/etc/nginx/nginx.conf --sbin-path=/usr/local/sbin/nginx --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx-error.log --user=nginx --group=nginx --http-client-body-temp-path=/var/tmp/nginx/client_body_temp --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi_temp --http-proxy-temp-path=/var/tmp/nginx/proxy_temp --http-scgi-temp-path=/var/tmp/nginx/scgi_temp --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi_temp --http-log-path=/var/log/nginx-access.log --add-module=/usr/ports/www/nginx/work/ngx_cache_purge-2.1 --with-http_geoip_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre --with-http_ssl_module
Nginx はインストール後に下記記事のようにディレクトリを構成しています。
設定ファイルは見通しを重視して、最小限のものを nginx.conf に記述、その他は conf.d/ 配下に置いた各種ファイルをインクルードするように構成してみます。
user nginx nginx;
pid /var/run/nginx.pid;
worker_processes 2;
worker_rlimit_nofile 4096;
events {
worker_connections 1024;
}
http {
include /usr/local/etc/nginx/mime.types;
default_type text/plain;
geo $noip {
default 0;
127.0.0.1 1;
}
gzip on;
gzip_http_version 1.0;
gzip_types text/plain
text/xml
text/css
text/javascript
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_comp_level 1;
gzip_buffers 4 8k;
gzip_min_length 1100;
log_format lb '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
sendfile on;
tcp_nopush on;
server_tokens off;
keepalive_requests 100;
keepalive_timeout 0;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_cache_path /home/www/cache/cache1 levels=1:2 keys_zone=cache1:512k inactive=1h max_size=390m;
proxy_cache_path /home/www/cache/cache2 levels=1:2 keys_zone=cache2:512k inactive=1h max_size=390m;
proxy_temp_path /home/www/temp;
server {
listen *:80 default_server;
root /home/nginx/htdocs;
access_log /var/log/nginx-access.log combined;
error_log /var/log/nginx-error.log warn;
location / {
if ($noip) { access_log off; }
if ($uri ~* "^/check.html$") { access_log off; }
index index.html;
}
}
include /usr/local/etc/nginx/conf.d/virtual.conf;
}
nginx.conf 中に記述した conf.d/virtual.conf の中身はこんな感じ。
server {
listen 80;
server_name worklog.be;
access_log /var/log/nginx-access.log lb;
error_log /var/log/nginx-error.log warn;
proxy_set_header X-Real-IP $http_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_max_temp_file_size 0;
set $do_not_cache 0;
set $proxy_cache_key "$scheme://$host$request_uri";
location / {
proxy_cache cache1;
include /usr/local/etc/nginx/conf.d/wordpress.conf;
proxy_pass http://192.168.0.101:80;
}
}
続いて、virtual.conf 中に記述した conf.d/wordpress.conf の中身はこんな感じ。
ここはコピペするだけなので以降は基本触らない。かなり大味だがキャッシュに関する制御とモバイルデバイス用のキャッシュキーを設定してある。
モバイルデバイスはもうちょっと厳密にやった方がいいけどとりあえずはこんな感じで。
proxy_no_cache $do_not_cache;
proxy_cache_bypass $do_not_cache;
proxy_cache_key $proxy_cache_key;
proxy_cache_valid 200 3d;
proxy_cache_valid any 1s;
if ($request_method != GET) {
set $do_not_cache 1;
}
if ($uri ~* "(feed|xmlrpc.php)$") {
set $do_not_cache 1;
}
if ($http_user_agent ~* ^.*(Android|iPhone|iPod).*) {
set $proxy_cache_key "mobile::$proxy_cache_key";
}
その他、必要なものは同じ要領で記述していけばソコソコ見やすいコンフィグになると思います。
後は、nginx -t で問題がなければ daemon を起動して Nginx 側は終わりです。
HAProxy と Nginx の連携
最後は HAProxy とNginx の連携です。
既にこの状態でも連携しているといえばしていますが、ヘルスチェック用の html を Nginx に置いていないのと HAProxy で必要な vip を listen させてないのでそれぞれやっていきます。
http --> [haproxy *1] -- req --> [nginx *2] -- req --> [apache] * [server] <= 物理サーバの凡例 * ip は下記を割り当て haproxy vip = 192.168.0.1, 192.168.0.2 proxy1 (nginx) ip = 192.168.0.51 proxy2 (nginx) ip = 192.168.0.52 www1 (apache) ip = 192.168.0.101 www2 (apache) ip = 192.168.0.102
キャッシュ対象はこのような流れにしたいので、virtual.conf に記述したプロキシ先の ip をまずは HAProxy に付与してあげます。(この場合は 192.168.0.101)
次は下記のように Nginx の DocumentRoot に html を置いてあげます。(構文は気にしなくて OK)
echo '<html>OK</html>' > /home/nginx/htdocs/check.html
これで HAProxy のヘルスチェックが up するのでバランシングされるようになります。
最後は worklog.be の zone を 192.168.0.1 に向けるとキャッシュ対象のトラフィックは上記のような経路で流れるようになり連携が完了です。
後は、Nginx 終端の Apache で log を tail しながら上手くコンテンツが分かれてリクエストされているかを確認します。Apache のアクセスログには HAProxy, Nginx の ip が記述されると思うので、必要であれば mod_rpaf 等で X-Forwarded-For ヘッダから変換してあげると良いです。
以上、HAProxy と Nginx を連携させたコンテンツキャッシュシステムはこれで一旦完成です。
Nginx 側はドメイン名単位で都度設定追加が必要な所ですが、HAProxy は収容ホスト (www1 とか) を予め羅列させて書いて置けば以降は vip の up/down だけで割りと汎用的には使えると思います。(一応そんな感じの使い方を想定しています。)
HAProxy は作成する TCP ソケットの数がどうしても多くなるのでこれで reload 等をしなくても良いはず!
とりあえず、書けるのはここまでなのですがこれから色々とテストをしてみようと思っているのでまた続きがあれば書きたいと思います。