オープンソースの HAProxy とNginx を組み合わせてコンテンツキャッシュシステムを構築するメモです。
リバースプロキシ型で動作するキャッシュシステムを構成して、既に動いている WordPress を何もしなくてもキャッシュで高速化できるようなものを作ってみたいと思います。
キャッシュだけなら Nginx の単体構成が低コストで手っ取り早いですが、今回つくるシステムはリバースプロキシ型で動作するので終端のサーバの事をあまり気にする必要がなく、既存の環境へも適用しやすいのがメリットです。(じゃないかと思っています。)
構成的には下記のような感じを予定しています。
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
今回、コンテンツキャッシュシステムとして構築するのは *1 と *2 の部分です。Apache は既に動いているものをそのまま使います。
概要としては、HAProxy で HTTP アクセスを制御 + 配下のキャッシュサーバ (Nginx) の死活をコントロール、Nginx でリバースプロキシ型の構成でキャッシュ。という感じです。
これを使う場合は、WordPress で使う独自ドメインを HAProxy の vip へ向けてやるという感じです。
コンテンツキャッシュシステム構築は前編と後編に分けて書こうと思いますが。今回は HAProxy 側から先に書きます。
スポンサーリンク
HAProxy の構成例
HAProxy は version 1.4.22 を使って、コンテンツ、サーバの振り分けとキャッシュサーバの死活監視ができるように設定してあげます。
Nginx の設定でも一応は絞りますが、キャッシュサーバに流すトラフィックとそうでないものを最初から HAProxy で分けてしまいます。
キャッシュサーバに流すトラフィック内容はこんな感じです。
- リクエストヘッダに text/html を含むもの
- リクエストヘッダに application/xhtml+xml を含むもの
- css および js ファイル
これ以外は全て Apache が動いているリアルサーバに直接流してやります。
ただし、下記の場合は除外します。
- wp-login.php へのアクセス
- wp-admin 配下へのアクセス
上記はキャッシュするとよろしくないので完全にキャッシュ対象外としてしまいます。
多分、こんな感じで足りるはず!
上記を元にした HAProxy コンフィグはこんな感じに。
global
log 127.0.0.1 local6 notice
maxconn 150000
daemon
nbproc 1
defaults
log 127.0.0.1 local6 info
retries 0
mode http
balance leastconn
timeout connect 30s
timeout server 30s
timeout client 30s
timeout check 5s
option httplog
option forwardfor
option httpchk GET /check.html HTTP/1.0
frontend multiple_frontend
bind :80
maxconn 130000
## ホストの判定
acl is_www1 dst 192.168.0.1
acl is_www2 dst 192.168.0.2
acl is_lb hdr_dom(host) -i lb.example.com
## http header の判定
acl is_cache hdr(Accept) -i text/html
acl is_cache hdr(Accept) -i application/xhtml+xml
acl is_cache path_end -i .css .css.gz .js .js.gz
## url path の判定
acl is_admin url -i /wp-login.php
acl is_admin url_dir -i /wp-admin/
## ここから宛先を振り分け
## is_lb が真の場合は haproxy のステータスを表示
use_backend lb_monitor if is_lb
## is_admin が偽、かつ、is_cache が真の場合はキャッシュサーバへ
use_backend dst_nginx_1 if ! is_admin is_cache
## is_www? が真の場合は対応するリアルサーバへ
use_backend dst_www1 if is_www1
use_backend dst_www2 if is_www2
## どれにもマッチしなければデフォルトサーバへ
default_backend dst_default
backend dst_nginx_1
server proxy1 192.168.0.51:80 check inter 5000 fall 2
server proxy2 192.168.0.52:80 check inter 5000 fall 2
backend dst_www1
server www 192.168.0.101:80
backend dst_www2
server www2 192.168.0.102:80
backend dst_default
server default 192.168.0.254:80
backend lb_monitor
log global
stats enable
stats show-legends
stats uri /hastats
stats auth haadmin:haadminpasss
ほぼそのままコピってるので長くなりました。
見通しの良さを重視して、1 つの frontend で処理できるように vip と 宛先 ip を結びつけるように書いているのがポイント。各種オプションも defaults ディレクティブに押し込んでいます。
後は、コンフィグチェックをして問題がなければ daemon を起動して HAProxy 側の構築は完了です。
今回は割愛していますが、HAProxy 自体も冗長化しておくのがベターかと思います。
※ ヘルスチェック は配下の DocumentRoot に置いた check.html を見るようにしているので注意。
今回初めて知りましたが、HAProxy の if で AND を使いたい場合は、「if is_hoge is_huga」のようにそのまま続けて書くらしい。
OR だと「if is_hoge or is_huga」か「if is_hoge || is_huga」なので、AND も「if is_hoge and is_huga」かと思ってたのにコンフィグチェックで怒られまくった。
※ ACL については公式ドキュメント 「7. Using ACLs and pattern extraction」を参照。
次は、Nginx 側について書きます。(つづく)