nginxで動くrestAPI用のリバースプロキシとしてvarnishを試したときのメモです。
「とりあえず動けば、、、」という感じなので各設定の解説とかはないです。
(いろんな詳しい記事を参考にさせて頂いたのですが、元ネタのURLをメモっておらず。。)
環境
- nginx, varnishの相乗り
- varnishは4.0.3を使用
コマンド等メモ
起動・停止・再起動
$ service varnish start|stop|restart
ログ
- デフォルトではファイルに出力されないので、コマンドで確認
- 運用時はファイルに出すこと
$ varnishlog
- コマンドのオプションでフィルタリングできるので色々調べると便利
管理コンソール
ほとんど使わなかった。。。
$ varnishadm
設定ファイルの構文チェック
$ varnishd -C -f /etc/varnish/default.vcl
キャッシュ
- デフォルトでキャッシュするステータスコード
200: OK
203: Non-Authoritative Information
300: Multiple Choices
301: Moved Permanently
302: Moved Temporarily
307: Temporary Redirect
410: Gone
404: Not Found
プロキシ設定
varnishとnginxの相乗り想定なので、ポートを変える程度。
varnishは80ポートでリクエストを受けて、nginxは8080でリクエストを受ける。
varnish設定変更
- varnishのLISTEN PORT変更
$ sudo vi /etc/sysconfig/varnish
VARNISH_LISTEN_PORT=80
- バックエンド設定変更
$ sudo vim /etc/varnish/default.vcl
backend default {
.host = "127.0.0.1";
.port = "8080";
}
nginx設定変更
$ sudo vi /etc/nginx/conf.d/hoge.conf
upstream backend {
ip_hash;
server 127.0.0.1:8080;
}
…
server {
…
listen 8080;
Varnish4.0.3
インストール
- 基本的には下記の手順でOK
$ wget http://dl.fedoraproject.org/pub/epel/6/x86_64/jemalloc-3.6.0-1.el6.x86_64.rpm
$ rpm -ivh jemalloc-3.6.0-1.el6.x86_64.rpm
$ rpm --nosignature -i https://repo.varnish-cache.org/redhat/varnish-4.0.el6.rpm
$ yum install -y varnish
EC2では、デフォルトのリポジトリをdisableする必要があった。
(そのままでもいけるという説もあり、別作業の変更がダメだったのかもしれません)
$ yum --enablerepo=varnish-4.0 --disablerepo=amzn-main,amzn-updates install varnish
VCL設定
varnishの挙動を設定するファイル。
C言語でいろいろ書ける。
デフォルトの/etc/varnish/default.vcl
を編集して、主に下記2点の対応を行った。
- URLのクエリパラメータ正規化
-
http://api/books?a=hoge&b=moge
とhttp://api/books?b=moge&a=hoge
は同じ内容キャッシュしないとダメだが、そのままでは別のキャッシュになってしまう - 4.X系では
boltsort
がstd(標準モジュール)に組み込まれた
-
- キャッシュの削除については、URLの正規表現でまとめて削除できる
smart ban
を使用- BANメソッドでリクエストが来た時に、そのURL(クエリパラメータを除く)をキーとするキャッシュを削除する使い方を想定
設定サンプル
※元々のメモから削除した箇所があるので、そのままでは動かない可能性があります。。
vcl 4.0;
import std;
# This is a basic VCL configuration file for varnish. See the vcl(7)
# man page for details on VCL syntax and semantics.
#
# Default backend definition. Set this to point to your content
# server.
#
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
# キャッシュ削除
if (req.method == "BAN") {
ban("obj.http.X-URL ~ ^" + req.url + "(\?.*)?$");
return (synth(200, "Banned."));
}
# 問答無用でクッキー削除(クッキーがセットされていてもキャッシュされてるっぽいので不要?)
#if (req.http.Cookie) {
# unset req.http.Cookie;
#}
# GETリクエストならキャッシュ
if (req.method == "GET") {
return(hash);
} else {
return(pass);
}
}
sub vcl_hash {
# urlをハッシュキーにする前に正規化する
set req.http.X-Cache-Key = req.url;
# boolパラメータを0, 1に統一する
set req.http.X-Cache-Key = regsuball(req.http.X-Cache-Key, "(?i)(\?|&)([^=]+)=true", "\1\2=1");
set req.http.X-Cache-Key = regsuball(req.http.X-Cache-Key, "(?i)(\?|&)([^=]+)=false", "\1\2=0");
# URIの末尾に"/"がついていた場合は除外する
set req.http.X-Cache-Key = regsuball(req.http.X-Cache-Key, "\/\?", "?");
set req.http.X-Cache-Key = regsuball(req.http.X-Cache-Key, "\/$", "");
# クエリパラメータのソート
set req.http.X-Cache-Key = std.querysort(req.http.X-Cache-Key);
hash_data(req.http.X-Cache-Key);
return (lookup);
}
sub vcl_backend_response {
# キャッシュ対象外の処理
if (
bereq.url ~ "^\/$" ||
bereq.url ~ "^\/index\.(html|php)" ||
bereq.url ~ "^\/phpinfo.php" ||
bereq.url ~ "^\/ocp.php"
) {
set beresp.uncacheable = true;
return (deliver);
}
# バックエンドからのレスポンスが200系でなければTTLを短くする
if (beresp.status > 300 && beresp.status != 304) {
set beresp.ttl = 10s;
}
# 圧縮されてない場合圧縮する
set beresp.do_gzip = true;
# デバッグ用にキャッシュキーをレスポンスヘッダにセットして返却する
set beresp.http.X-Cache-Key = bereq.http.X-Cache-Key;
}
sub vcl_deliver {
## Varnishのキャッシュ情報をレスポンスヘッダーに付与
if(!resp.http.X-Served-By) {
set resp.http.X-Served-By = server.identity;
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
}
else {
set resp.http.X-Cache = "MISS";
}
// キャッシュのヒット回数
set resp.http.X-Cache-Hits = obj.hits;
}
else {
# append current data
set resp.http.X-Served-By = regsub(resp.http.X-Served-By, "$", ", ");
set resp.http.X-Served-By = regsub(resp.http.X-Served-By, "$", server.identity);
if (obj.hits > 0) {
set resp.http.X-Cache = regsub(resp.http.X-Cache, "$", ", HIT");
}
else {
set resp.http.X-Cache = regsub(resp.http.X-Cache, "$" , ", MISS");
}
set resp.http.X-Cache-Hits = regsub(resp.http.X-Cache-Hits, "$", ", ");
set resp.http.X-Cache-Hits = regsub(resp.http.X-Cache-Hits, "$", obj.hits);
}
## remove Varnish header
unset resp.http.Via;
unset resp.http.X-Varnish;
unset resp.http.X-Served-by;
unset resp.http.X-URL;
}