SR キャッシュ

Name

ngx_srcache - 任意のNGINX locationのための透過的なサブリクエストベースのキャッシュレイアウト

注意

このモジュールはNGIXのソースと一緒に配布されません。 インストレーションの説明を見てください。

状態

このモジュールはプロダクションの準備ができています。

バージョン

このドキュメントは2015年2月18日にリリースされたsrcache-nginx-module v0.29 を説明します。

概要

upstream my_memcached {
    server 10.62.136.7:11211;
    keepalive 10;
}

location = /memc {
    internal;

    memc_connect_timeout 100ms;
    memc_send_timeout 100ms;
    memc_read_timeout 100ms;
    memc_ignore_client_abort on;

    set $memc_key $query_string;
    set $memc_exptime 300;

    memc_pass my_memcached;
}

location /foo {
    set $key $uri$args;
    srcache_fetch GET /memc $key;
    srcache_store PUT /memc $key;
    srcache_store_statuses 200 301 302;

    # proxy_pass/fastcgi_pass/drizzle_pass/echo/etc...
    # or even static files on the disk
}
location = /memc2 {
    internal;

    memc_connect_timeout 100ms;
    memc_send_timeout 100ms;
    memc_read_timeout 100ms;
    memc_ignore_client_abort on;

    set_unescape_uri $memc_key $arg_key;
    set $memc_exptime $arg_exptime;

    memc_pass unix:/tmp/memcached.sock;
}

location /bar {
    set_escape_uri $key $uri$args;
    srcache_fetch GET /memc2 key=$key;
    srcache_store PUT /memc2 key=$key&exptime=$srcache_expire;

    # proxy_pass/fastcgi_pass/drizzle_pass/echo/etc...
    # or even static files on the disk
}
map $request_method $skip_fetch {
    default     0;
    POST        1;
    PUT         1;
}

server {
    listen 8080;

    location /api/ {
        set $key "$uri?$args";

        srcache_fetch GET /memc $key;
        srcache_store PUT /memc $key;

        srcache_methods GET PUT POST;
        srcache_fetch_skip $skip_fetch;

        # proxy_pass/drizzle_pass/content_by_lua/echo/...
    }
}

説明

SR キャッシュモジュールは任意のNGINX locationのために(それらがupstramあるいは静的ディスクファイルを提供するかのように)透過的なキャッシュレイヤーを提供します。キャッシュの挙動は RFC 2616とほとんど互換性があります。

通常、Memcは具体的なキャッシュストレージバックエンドを提供するためにこのモジュールと一緒に使われます。しかし技術的には、RESTインタフェースを提供するどのようなモジュールも、このモジュールによって利用される取得および格納サブリクエストとして使われることができます。

メインのリクエストに関して、srcache_fetch ディレクティブはアクセスフェーズの最後に動作し、そのため標準的なアクセスモジュールallow および deny ディレクティブは 先に実行されます。このことはセキュリティ的な理由で通常は望ましい挙動です。

このモジュールの処理の流れは以下のようになります:

http://agentzh.org/misc/image/srcache-flowchart.png

サブリクエストのキャッシング

サブリクエストに関しては、正しくするのが困難なためこのモジュールの使用は明示的に 許可されません。以前は実装されていましたが、バグが多く最終的にその修正を諦め破棄しました。

しかし、Luaを使っている場合は、Luaの中で独力でサブリクエストをキャッシュすることは容易です。That is, first issue a subrequest to an Memc location to do an explicit cache lookup, if cache hit, just use the cached data returned; otherwise, fall back to the true backend, and finally do a cache insertion to feed the data into the cache.

メインのリクエストのキャッシングのためにこのモジュールを追懐、サブリクエストのキャッシングのためにLuaを使うのがビジネスで行うやり方です。この混成の解決方法はプロダクションでとても良く動作します。

分散型memcachedキャッシュ

このモジュールの上に構築された分散型memcachedキャッシュの仕組みの簡単な例です。3つの異なるmemcachedノードがあり、キーをハッシュするために簡単なmoduloを使うとします。

http {
    upstream moon {
        server 10.62.136.54:11211;
        server unix:/tmp/memcached.sock backup;
    }

    upstream earth {
        server 10.62.136.55:11211;
    }

    upstream sun {
        server 10.62.136.56:11211;
    }

    upstream_list universe moon earth sun;

    server {
        memc_connect_timeout 100ms;
        memc_send_timeout 100ms;
        memc_read_timeout 100ms;

        location = /memc {
            internal;

            set $memc_key $query_string;
            set_hashed_upstream $backend universe $memc_key;
            set $memc_exptime 3600; # in seconds
            memc_pass $backend;
        }

        location / {
            set $key $uri;
            srcache_fetch GET /memc $key;
            srcache_store PUT /memc $key;

            # proxy_pass/fastcgi_pass/content_by_lua/drizzle_pass/...
        }
    }
}

上の例で起きていることは以下のようなことです:

  1. まず3つのupstreamを定義します。moon, earth および sun。3つのmemcachedサーバがあります。
  2. そして、Set Miscによって提供されるupstream_listディレクティブを使って、universeという名前のupstream list エンティティとしてそれらをグループ化します。
  3. その後、memcachedクラスタに通信するために/memc という名前の内部locationを定義します。
  4. この /memc locationの中で、まずクエリ文字列($args)と一緒に$memc_key 変数を設定し、それからupstream list universe上に$memc_keyをハッシュするために set_hashed_upstreamディレクティブを使用し、変数 $backendに割り当てられるように具体的なupstream名を取得します。
  5. この $backend 変数をmemc_pass ディレクティブに渡します。$backend 変数は、moon, earth および sunのうちの値を持つことができます。
  6. また、 $memc_exptime変数を上書くことで、memcachedのキャッシングの有効期限を3600秒(つまり1時間)に定義します。
  7. 主要なpublic location / の中で、キャッシュキーとして$uri 変数を定義し、キャッシュの検査のためにsrcache_fetchとキャッシュの更新のためにsrcache_store を設定します。これらの2つのディレクティブの中で以前に定義された /memc location への2つのサブリクエストを使用していあmす。

上の例の中で$backend および/あるいは $key 変数を計算するために独自のLuaコードを入れるために、Luaset_by_lua あるいは rewrite_by_lua ディレクティブを使うことができます。

気をつけなければいけない事は、memcachedはキーの長さに制限、つまり250バイト、があるということです。そのためとても長いかも知れないキーのために、/memc locationなどの$memc_keyに割り当てる前にキーを固定長のダイジェストにプリハッシュするために、set_md5 ディレクティブあるいはその類型を使うかも知れません。

更に、何をキャッシュし何をキャッシュしないかをリクエスト単位で制御するために srcache_fetch_skip および srcache_store_skip ディレクティブを使うことができ、Luaも同じやり方でここで使うことができます。つまり、可能性は本当に無限大です。

スピードを最大化するために、 keepaliveによって提供されるmemcached upstreamのためにしばしばTCP(あるいはUnixドメインソケット)接続プールを有効にします。例えば、

upstream moon {
    server 10.62.136.54:11211;
    server unix:/tmp/memcached.sock backup;
    keepalive 10;
}

ここで、moon upstream (クラスタ)のために10個までのkeep-alive接続(NGINXワーカープロセスあたり)を保持できる接続プールを定義しています。

Redisを使ったキャッシング

memcached が後ろにあるキャッシングの1つの厄介な点は、memcached サーバの1MBの値のサイズ制限です。つまり、このモジュールのバックエンドとして提供するためにRedisのような寛容なバックエンドストレージを使いたいと思うことがしばしばあります。

Redisを使った動作例です:

location /api {
    default_type text/css;

    set $key $uri;
    set_escape_uri $escaped_key $key;

    srcache_fetch GET /redis $key;
    srcache_store PUT /redis2 key=$escaped_key&exptime=120;

    # fastcgi_pass/proxy_pass/drizzle_pass/postgres_pass/echo/etc
}

location = /redis {
    internal;

    set_md5 $redis_key $args;
    redis_pass 127.0.0.1:6379;
}

location = /redis2 {
    internal;

    set_unescape_uri $exptime $arg_exptime;
    set_unescape_uri $key $arg_key;
    set_md5 $key;

    redis2_query set $key $echo_request_body;
    redis2_query expire $key $exptime;
    redis2_pass 127.0.0.1:6379;
}

この例はHTTP Echo Moduleによって提供される$echo_request_body 変数を利用しています。以前のバージョンは信頼できる動作をしないかも知れないため、HTTP Echo Moduleの最新バージョン、 v0.38rc2 が必要なことに注意してください。

また、HTTP RedisRedis2の両方が必要です。前者は srcache_fetch サブリクエストの中で使われ、校舎はsrcache_store サブリクエストの中で使われます。

NGINXコアはRedis2のパイプラインが特定の極限の条件下で適切に動作させないバグもあります。そして、以下のパッチがこれを修正します:

http://mailman.nginx.org/pipermail/nginx-devel/2012-March/002040.html

しかし、もし ngx_openresty 1.0.15.3以降の bundleを使っている場合は、bundler内にここで必要なものを全て持っていることに注意してください。

キャッシュキー処理

キャッシュのヒット率を損なうかも知れないランダムノイズを除外するために、キャッシュキーの前処理をすることが望ましいことがしばしばあります。例えば、URI引数内のランダムセッションIDは通常削除されることが望ましいです。

以下のURIクエリ文字列を考えてみましょう:

SID=BC3781C3-2E02-4A11-89CF-34E5CFE8B0EF&UID=44332&L=EN&M=1&H=1&UNC=0&SRC=LK&RT=62

それからSIDUID 引数を削除したいと思います。同時に Lua を使う場合は、それをするのはとても簡単です。

location = /t {
    rewrite_by_lua '
        local args = ngx.req.get_uri_args()
        args.SID = nil
        args.UID = nil
        ngx.req.set_uri_args(args)
    ';

    echo $args;
}

ここで最後に$argsの最終の値を出力するためにHTTP Echo Moduleechoディレクティブを使います。この場合、それを代わりにSR Cache 設定とupstream設定で置き換えることができます。この /t インタフェースをcurlを使ってテストしてみましょう:

$ curl 'localhost:8081/t?RT=62&SID=BC3781C3-2E02-4A11-89CF-34E5CFE8B0EF&UID=44332&L=EN&M=1&H=1&UNC=0&SRC=LK'
M=1&UNC=0&RT=62&H=1&L=EN&SRC=LK

It is worth mentioning that, if you want to retain the order of the URI arguments, then you can do string substitutions on the value of $args directly, for example:

location = /t {
    rewrite_by_lua '
        local args = ngx.var.args
        newargs, n, err = ngx.re.gsub(args, [[\b[SU]ID=[^&]*&?]], "", "jo")
        if n and n > 0 then
            ngx.var.args = newargs
        end
    ';

    echo $args;
}

元のcurlコマンドで再びそれをテストし、完全に期待しているものを得ます:

RT=62&L=EN&M=1&H=1&UNC=0&SRC=LK

しかし、キャッシュの目的にはキャッシュのヒット率を増加させることができるようにURI引数の順番を正規化するのが良いでしょう。そして、LuaJITあるいはLuaによって使われるハッシュテーブル エントリーの順番は、良い副作用として順番を正規化するのに使うことができます。

ディレクティブ

srcache_fetch

構文:srcache_fetch <method> <uri> [args]...
デフォルト:none
コンテキスト:http, server, location, location if
Phase:post-access

このディレクティブはキャッシュを調査するためにNGINXサブリクエストを発行するアクセスフェイズハンドラーを登録します。

サブリクエストが 200以外を返す場合、キャッシュミスが発信され、コントロールフローはngx_http_proxy_module, ngx_http_fastcgi_module およびその他によって設定されたコンテントフェイズを含む後段のフェーズを続けるでしょう。サブリクエストが 200 OKを返す場合、キャッシュヒットが発信され、このモジュールはサブリクエストの応答を現在のメインリクエストの応答としてクライアントに直接送信するでしょう。

このディレクティブは常にアクセスフェーズの最後に実行し、ngx_http_access_moduleの allow および denyは常にこのに実行するでしょう。

キャッシュの選択的な調査を無効にするために srcache_fetch_skip ディレクティブを使うことができます。

srcache_fetch_skip

構文:srcache_fetch_skip <flag>
デフォルト:0
コンテキスト:http, server, location, location if
Phase:post-access

<flag> 引数はNGINX変数をサポートします。この引数の値が空では無く、かつ 0に等しくない場合、取得プロセスは無条件にスキップされるでしょう。

例えば、fooという名前でbarという値のクッキーを持つリクエストのキャッシュをスキップするには、以下のように書けます

location / {
    set $key ...;
    set_by_lua $skip '
        if ngx.var.cookie_foo == "bar" then
            return 1
        end
        return 0
    ';

    srcache_fetch_skip $skip;
    srcache_store_skip $skip;

    srcache_fetch GET /memc $key;
    srcache_store GET /memc $key;

    # proxy_pass/fastcgi_pass/content_by_lua/...
}

ここで、(以前の)rewriteフェーズで$skip変数の値を計算するためにLua が使われます。同様に、$key 変数は set_by_lua あるいは rewrite_by_lua ディレクティブを使ってLuaによって計算することもできます。

上の例の$skip 変数の値を計算するために、標準的なmapディレクティブを使うこともできます:

map $cookie_foo $skip {
    default     0;
    bar         1;
}

しかし、map ステートメントはnginx.confファイルの http 設定ブロックに配置する必要があります。

srcache_store

構文:srcache_store <method> <uri> [args]...
デフォルト:none
コンテキスト:http, server, location, location if
Phase:output-filter

このディレクティブは現在のメインのリクエストの応答をキャッシュバックエンドに保存するためにNGINXサブリクエストを発行するだろう出力フィルタハンドラを登録します。サブリクエストのステータスコードは無視されるでしょう。

キャッシュミスをした場合特定のリクエストのキャッシュを無効にするために srcache_store_skip および srcache_store_max_size ディレクティブを使うことができます。

v0.12rc7 リリースから、応答ステータス行、応答ヘッダ、および応答ボディがキャッシュに置かれます。デフォルトでは、以下の特別な応答ヘッダはキャッシュされないでしょう:

  • Connection
  • Keep-Alive
  • Proxy-Authenticate
  • Proxy-Authorization
  • TE
  • Trailers
  • Transfer-Encoding
  • Upgrade
  • Set-Cookie

どのヘッダをキャッシュしどのヘッダをキャッシュしないかを盛業するために srcache_store_pass_header および/あるいはr srcache_store_hide_header ディレクティブを使うことができます。

元の応答データチャンクは到着するとすぐに削除されます。srcache_store just copies and collects the data in an output filter without postponing them from being sent downstream.

しかし、全ての応答データがすぐに送信されるとしても、現在のNGINXリクエストの生存期間はsrcache_storeサブリクエストが完了するまで終了しないということに注意してください。That means a delay in closing the TCP connection on the server side (when HTTP keepalive is disabled, but proper HTTP clients should close the connection actively on the client side, which adds no extra delay or other issues at all) or serving the next request sent on the same TCP connection (when HTTP keepalive is in action).

srcache_store_max_size

構文:srcache_store_max_size <size>
デフォルト:0
コンテキスト:http, server, location, location if
Phase:output-header-filter

応答ボディの長さがこのサイズを超える場合、このモジュールは srcache_storeで指定されるサブリクエストのテンプレートを使ってキャッシュに応答ボディを格納しようとしないでしょう。

こんれは入力データにハード的な上限を持つキャッシュストレージバックエンドを使う場合に特に有用です。例えば、memcachedサーバの場合、その上限は通常 1 MBです。

0 が指定された場合(デフォルト値)、キャッシュには全く制限がありません。

srcache_store_skip

構文:srcache_store_skip <flag>
デフォルト:0
コンテキスト:http, server, location, location if
Phase:output-header-filter

<flag> 引数はNGINX変数をサポートします。この引数の値が空では無く、かつ 0に等しくない場合、格納プロセスは無条件にスキップされるでしょう。

v0.25 リリースから、(NGINX変数を含むかも知れない)<flag> 表現は2回まで評価されるかも知れません: 最初は応答ヘッダが送信された直後で、<flag> 表現がtrueに評価されない場合は応答ボディデータ ストリームの終わりが見えた直後に再び評価されるでしょう。v0.25の前は最初の評価のみが実施されます。

"/tmp"文字列を含むURIを格納することを避けるためにLuaを使って$nocacheを設定する例です:

set_by_lua $nocache '
    if string.match(ngx.var.uri, "/tmp") then
        return 1
    end
    return 0';

srcache_store_skip $nocache;

srcache_store_statuses

構文:srcache_store_statuses <status1> <status2>...
デフォルト:200 301 302
コンテキスト:http, server, location, location if
Phase:output-header-filter

このディレクティブはステータスコードに応じてキャッシュにどのような応答を格納するかを制御します。

デフォルトでは、200, 301および 302 応答がキャッシュに格納され、それ以外の応答はsrcache_storeをスキップするでしょう。

任意の正の数をキャッシュしたい応答ステータスとして指定することができます。404 および 503のようなエラーコードも含めることができます。例えば:

srcache_store_statuses 200 201 301 302 404 503;

少なくとも一つの引数がこのディレクティブに渡されなければなりません。

このディレクティブはv0.13rc2 リリースで初めて導入されました。

srcache_store_ranges

構文:srcache_store_ranges [ on | off ]
デフォルト:off
コンテキスト:http, server, location, location if
Phase:output-body-filter

このディレクティブが有効な場合、srcache_store は標準の ngx_http_range_filter_moduleによって生成された206 Partial Content 応答も格納するでしょう。このディレクティブをonにすると、キャッシュキーに$http_rangeを追加しなければなりません。例えば:

location / {
    set $key "$uri$args$http_range";
    srcache_fetch GET /memc $key;
    srcache_store PUT /memc $key;
}

このディレクティブは v0.27 リリースで初めて導入されました。

srcache_header_buffer_size

構文:srcache_header_buffer_size <size>
デフォルト:4k/8k
コンテキスト:http, server, location, location if
Phase:output-header-filter

このディレクティブはsrcache_storeのために応答ヘッダをシリアライズする場合にヘッダバッファを制御します。デフォルトのサイズはページサイズで、プラットフォームに依存し通常 4k あるいは 8kです。

バッファは全ての応答ヘッダでは無く個々のヘッダだけを維持するために使われることに注意してください。つまりバッファは最も長い応答ヘッダを保持するのに十分な大きさである必要があるだけです。

このディレクティブは v0.12rc7 リリースで初めて導入されました。

srcache_store_hide_header

構文:srcache_store_hide_header <header>
デフォルト:no
コンテキスト:http, server, location, location if
Phase:output-header-filter

デフォルトではこのモジュールは以下を除いた全ての応答ヘッダをキャッシュします:

  • Connection
  • Keep-Alive
  • Proxy-Authenticate
  • Proxy-Authorization
  • TE
  • Trailers
  • Transfer-Encoding
  • Upgrade
  • Set-Cookie

このディレクティブによってそれらの名前(大文字小文字を気にしない)をリスト化することでsrcache_storeから応答ヘッダを隠すことさえできます。例えば、

srcache_store_hide_header X-Foo;
srcache_store_hide_header Last-Modified;

一つのlocationにこのディレクティブを複数おくことができます。

このディレクティブは v0.12rc7 リリースで初めて導入されました。

srcache_store_pass_headerも見てください。

srcache_store_pass_header

構文:srcache_store_pass_header <header>
デフォルト:no
コンテキスト:http, server, location, location if
Phase:output-header-filter

デフォルトではこのモジュールは以下を除いた全ての応答ヘッダをキャッシュします:

  • Connection
  • Keep-Alive
  • Proxy-Authenticate
  • Proxy-Authorization
  • TE
  • Trailers
  • Transfer-Encoding
  • Upgrade
  • Set-Cookie

このディレクティブを使ってそれらの名前(大文字小文字を気にしない)をリスト化することでsrcache_storeからsrcache_storeが1つ以上のそれらの応答ヘッダを格納するように強制することができます。 例えば、

srcache_store_pass_header Set-Cookie;
srcache_store_pass_header Proxy-Autenticate;

一つのlocationにこのディレクティブを複数おくことができます。

このディレクティブは v0.12rc7 リリースで初めて導入されました。

srcache_store_hide_headerも見てください。

srcache_methods

構文:srcache_methods <method>...
デフォルト:GET HEAD
コンテキスト:http, server, location
Phase:post-access, output-header-filter

このディレクティブはsrcache_fetch あるいは srcache_storeのどちらかによって考慮されるHTTPリクエストメソッドを指定することができます。リスト化されていないHTTP リクエストメソッドはキャッシュから完全に抜かされます。

以下のHTTPメソッドが許可されます: GET, HEAD, POST, PUT および DELETE. GETHEAD メソッドはこのディレクティブにあるかどうかに関係なく常に暗黙的に含まれます。

v0.17 リリースから HEAD リクエストはそれらの応答がリクエストボディを運ばないため、常にsrcache_storeによって抜かされることに注意してください。

このディレクティブは v0.12rc7 リリースで初めて導入されました。

srcache_ignore_content_encoding

構文:srcache_ignore_content_encoding [ on | off ]
デフォルト:off
コンテキスト:http, server, location, location if
Phase:output-header-filter

このディレクティブがoff (デフォルト)にされた場合、空では無い Content-Encoding 応答ヘッダは srcache_store に全ての応答をキャッシュに格納することを抜けさせ、以下のようにNGINXのerror.log に警告を発行します:

[warn] 12500#0: *1 srcache_store skipped due to response header "Content-Encoding: gzip"
            (maybe you forgot to disable compression on the backend?)

このディレクティブをonにすると Content-Encoding 応答ヘッダを無視し、通常のように(そして警告無しに)応答を格納するでしょう。

以下の行をnginx.conf ファイルに指定することで、バックエンドサーバ上の gzip/deflate圧縮を常に無効にすることをお勧めします:

proxy_set_header  Accept-Encoding  "";

このディレクティブは v0.12rc7 リリースで初めて導入されました。

srcache_request_cache_control

構文:srcache_request_cache_control [ on | off ]
デフォルト:off
コンテキスト:http, server, location
Phase:post-access, output-header-filter

このディレクティブが onの場合、リクエストヘッダ Cache-ControlPragma は以下の方法でこのモジュールによって引き受けられるでしょう:

  1. srcache_fetch、つまりキャッシュのlookup操作は、リクエストヘッダ Cache-Control: no-cache および/あるいは Pragma: no-cache が存在する場合に抜かされるでしょう。
  2. srcache_store、つまりキャッシュ格納操作は、リクエストヘッダ Cache-Control: no-store が指定された場合に抜かされるでしょう。

このディレクティブをoffにすると、この機能は無効にされ、スピードを主にキャッシュに頼っている忙しいサイトにとってより安全と考えられます。

このディレクティブは v0.12rc7 リリースで初めて導入されました。

srcache_response_cache_controlも見てください。

srcache_response_cache_control

構文:srcache_response_cache_control [ on | off ]
デフォルト:on
コンテキスト:http, server, location
Phase:output-header-filter

このディレクティブがonの場合、応答ヘッダCache-ControlExpires は以下の方法でこのモジュールによって引き受けられるでしょう:

このディレクティブは srcache_store_no_store, srcache_store_no_cache および srcache_store_private ディレクティブに優先されます。

このディレクティブは v0.12rc7 リリースで初めて導入されました。

srcache_request_cache_controlも見てください。

srcache_store_no_store

構文:srcache_store_no_store [ on | off ]
デフォルト:off
コンテキスト:http, server, location
Phase:output-header-filter

このディレクティブをonにすると、srcache_response_cache_controlon にされ 他の上限が一致した場合に、Cache-Control: no-store のヘッダを持つ応答を強制的にキャッシュに格納させるでしょう。デフォルトはoffです。

このディレクティブは v0.12rc7 リリースで初めて導入されました。

srcache_store_no_cache

構文:srcache_store_no_cache [ on | off ]
デフォルト:off
コンテキスト:http, server, location
Phase:output-header-filter

このディレクティブをonにすると、srcache_response_cache_controlon にされ 他の上限が一致した場合に、Cache-Control: no-cache のヘッダを持つ応答を強制的にキャッシュに格納させるでしょう。デフォルトはoffです。

このディレクティブは v0.12rc7 リリースで初めて導入されました。

srcache_store_private

構文:srcache_store_private [ on | off ]
デフォルト:off
コンテキスト:http, server, location
Phase:output-header-filter

このディレクティブをonにすると、srcache_response_cache_controlon にされ 他の上限が一致した場合に、Cache-Control: private のヘッダを持つ応答を強制的にキャッシュに格納させるでしょう。デフォルトはoffです。

このディレクティブは v0.12rc7 リリースで初めて導入されました。

srcache_default_expire

構文:srcache_default_expire <time>
デフォルト:60s
コンテキスト:http, server, location, location if
Phase:output-header-filter

このディレクティブは、Cache-Control: max-age=N あるいは Expiresのどちらも応答ヘッダ内に指定されていない場合に、$srcache_expire 変数の値のデフォルトの有効期限を制御します。

デフォルトでは<time> 引数は秒数です。しかし混乱を避けるために常に明示的に時間単位を設定するのが懸命です。時間単位は“s”(seconds), “ms”(milliseconds), “y”(years), “M”(months), “w”(weeks), “d”(days), “h”(hours), and “m”(minutes) がサポートされます。例えば:

srcache_default_expire 30m; # 30 minutes

この時間は597時間未満に設定すべきです。

このディレクティブは v0.12rc7 リリースで初めて導入されました。

srcache_max_expire

構文:srcache_max_expire <time>
デフォルト:0
コンテキスト:http, server, location, location if
Phase:output-header-filter

このディレクティブは$srcache_expire 変数の値の最大の有効期限を制御します。この設定は他の計算メソッドよりも優先されます。

デフォルトでは<time> 引数は秒数です。しかし混乱を避けるために常に明示的に時間単位を設定するのが懸命です。時間単位は“s”(seconds), “ms”(milliseconds), “y”(years), “M”(months), “w”(weeks), “d”(days), “h”(hours), and “m”(minutes) がサポートされます。例えば:

srcache_max_expire 2h;  # 2 hours

この時間は597時間未満に設定すべきです。

デフォルトの設定の0が指定された場合、全く制限がない でしょう。

このディレクティブは v0.12rc7 リリースで初めて導入されました。

変数

$srcache_expire

このNGINXの整数値はキャッシュに格納される現在の応答の推奨される有効期限(秒数)を表します。値の計算アルゴリズムは以下の通りです:

  1. 応答ヘッダCache-Control: max-age=N が指定された場合、期限切れの時間としてN が使われるでしょう。
  2. そうでなければ、もし応答ヘッダExpires が指定された場合は、期限切れ時間はExpiresヘッダに指定された時間から現在のタイムスタンプを引くことで得られます。
  3. Cache-Control: max-age=N あるいは Expires ヘッダのどちらも指定されない場合は、srcache_default_expire ディレクティブに指定された値が使われます。

もし上でのアルゴリズムで得られる値が最大値(もしあれば)を超える場合は、この変数の最後の値は、srcache_max_expireで指定される値でしょう。

期限切れの時間としてこの変数を使う必要はありません。

この値はv0.12rc7 リリースで初めて導入されました。

$srcache_fetch_status

このNGINX変数はキャッシングシステムにとって"fetch"フェイズの状態と等価です。3つの値を取り得ます。HIT, MISSおよび BYPASS

"fetch"サブリクエストが200 以外のステータスを返すか、応答データが良く整形されていない場合は、この変数がMISSと等価になります。

The value of this variable is only meaningful after the access request processing phase, or BYPASS is always given.

この変数はv0.14 リリースで初めて導入されました。

$srcache_store_status

このNGINX変数は"store"フェーズのための現在のキャッシングステータスを渡します。2つの値が取り得ます。STOREBYPASS が得られるでしょう。

"store"サブリクエストの応答は常に破棄されるため、この変数の値は"store"サブリクエストが実際に発行される限り常に STOREでしょう。

この変数の値は少なくとも現在(主要な)リクエストが送信される場合に限り意味があります。Content-Length応答ヘッダが主要なリクエストのために指定されない場合は、最後の結果は全てのコンテンツボディが送信された後でのみ取得できるでしょう。

この変数はv0.14 リリースで初めて導入されました。

知られている問題

  • あるシステムでは、aio および/あるいは sendfile を有効にすると作業中のsrcache_store を停止するかも知れません。srcache_storeによって設定されるlocationの中で無効にすることができます。
  • srcache_store ディレクティブはecho_subrequest_async および echo_locationのようなHTTP Echo Moduleのサブリクエスト ディレクティブによって生成された応答をキャプチャするために使うことができません。サブリクエストを初期下およびキャプチャを初期化するためにngx_lua を使うことがお勧めです。これは srcache_storeと一緒に動作するはずです。

警告

  • バックエンドのgzip圧縮を無効にし、それをするためにNGINXのngx_http_gzip_moduleを使うことをお勧めします。ngx_http_proxy_moduleの場合、バックエンドgzip圧縮を無効にするために以下の設定を使うことができます。

    proxy_set_header  Accept-Encoding  "";
    
  • "if は邪悪"なため、このモジュールのifとして同じlocation内で ngx_http_rewrite_moduleのif ディレクティブを使わないでください。代わりに ngx_http_map_module あるいは srcache_store_skip および/あるいは srcache_fetch_skipLua と組み合わせて使ってください。例えば:

    map $request_method $skip_fetch {
        default     0;
        POST        1;
        PUT         1;
    }
    
    server {
        listen 8080;
    
        location /api/ {
            set $key "$uri?$args";
    
            srcache_fetch GET /memc $key;
            srcache_store PUT /memc $key;
    
            srcache_methods GET PUT POST;
            srcache_fetch_skip $skip_fetch;
    
            # proxy_pass/drizzle_pass/content_by_lua/echo/...
        }
    }
    

トラブルシューティング

問題をデバッグするために、まずNGINXのerror.log ファイルを常に調べるべきです。エラーメッセージが出力されない場合は、debugging logで説明されたように、もっと詳細を得るためにNGINXデバッギングログを有効にする必要があります。

初心者のための幾つかの共通の落とし穴:

  • 元の応答は明示的にキャッシングを無効にするCache-Controlヘッダを運び、 srcache_response_cache_controlのようなディレクティブを設定しません。
  • 元の応答は常にgzip圧縮されています。これはデフォルトでキャッシュされません(srcache_ignore_content_encodingを見てください)。

インストール

このモジュールをNGINX コアと ngx_openresty bundleを使って多くの他のものと一緒にインストールすることをお勧めします。これは準備をするのに最も簡単で最も安全な方法です。詳細はOpenRestyのインストール手順を見てください。

別のやり方として、全て自分自身でこのモジュールと一緒にNGINXをビルドすることができます:

  • NGIXNのソースコード、例えばバージョン1.7.10 ([[#Compatibility|NGINX Compatibility]]を見てください)をnginx.orgからダウンロードします。

  • そして、主流のNGINXコアの重要なバグを修正するパッチをNGINXソースツリーに適用します: https://raw.githubusercontent.com/openresty/ngx_openresty/master/patches/nginx-1.4.3-upstream_truncation.patch (NGINX 1.5.3以降を使う場合は、このパッチは必要ありません。)

  • その後で、このモジュールの最新バージョンのリリースtarballを srcache-nginx-module file list からダウンロードします。

  • 最後にこのモジュールと一緒にNGINXをビルドします。

    wget 'http://nginx.org/download/nginx-1.7.10.tar.gz'
    tar -xzvf nginx-1.7.10.tar.gz
    cd nginx-1.7.10/
    
    # Here we assume you would install you nginx under /opt/nginx/.
    ./configure --prefix=/opt/nginx \
         --add-module=/path/to/srcache-nginx-module
    
    make -j2
    make install
    

互換性

NGINXの以下のバージョンがこのモジュールで動作するはずです:

  • 1.7.x (最後のテスト: 1.7.10)
  • 1.5.x (最後のテスト: 1.5.12)
  • 1.4.x (最後のテスト: 1.4.4)
  • 1.3.x (最後のテスト: 1.3.7)
  • 1.2.x (最後のテスト: 1.2.9)
  • 1.1.x (最後のテスト: 1.1.5)
  • 1.0.x (最後のテスト: 1.0.11)
  • 0.9.x (最後のテスト: 0.9.4)
  • 0.8.x >= 0.8.54 (最後のテスト: 0.8.54)

0.7.x, 0.6.x and 0.5.x のようなNGINXの以前のバージョンは動作しない でしょう。

0.7.44以上のNGINXの特定のバージョンでこのモジュールが動作しないことを見つけたら、バグの報告を考えてみてください。

コミュニティ

英語のメーリングリスト

openresty-en メーリングリストは英語を話す人のためのものです。

中国語のメーリングリスト

openresty メーリングリストは中国語を話す人のためのものです。

バグとパッチ

バグレポート、欲しいもののリスト、あるいはパッチを下記でサブミットしてください

  1. GitHub Issue Tracker上でチケットを作成
  2. あるいは、OpenResty communityにポスト。

ソースリポジトリ

github上のopenresty/srcache-nginx-moduleで利用可能です。

テストスィート

このモジュールはPerl駆動テストスィートが付いています。test casesdeclarative です。Perl世界の Test::Nginx <http://search.cpan.org/perldoc?Test::Base> モジュールに感謝します。

アナタの側でそれを実行するには:

$ PATH=/path/to/your/nginx-with-srcache-module:$PATH prove -r t

NGINXサーバ バイナリを変更した場合はテストスィートを実行する前に全てのNGINXプロセスを終了する必要があります。

単一のNGINX サーバ (デフォルトでは localhost:1984) は全てのテストスクリプト(.t ファイル)に渡って使用されるため、proveユーティリティを起動する時に-jNを指定することで並行してテストスィートを実行することは意味がありません。

Some parts of the test suite requires modules ngx_http_rewrite_module, HTTP Echo Module, HttpRdsJsonModule, and Drizzle to be enabled as well when building NGINX.

TODO

  • add gzip compression and decompression support.
  • add new NGINX variable $srcache_key and new directives srcache_key_ignore_args, srcache_key_filter_args, and srcache_key_sort_args.

Getting involved

Authorにパッチをサブミット、あるいはGitHub上のSource Repositoryに少しコミットするように依頼することをとても歓迎します。

Author

Yichun “agentzh” Zhang (章亦春) <agentzh@gmail.com>, CloudFlare Inc.