Memc

Name

ngx_memc - set, add,delete およびもっと多くのmemcachedコマンドをサポートする標準のmemcachedモジュールの拡張バージョンです。

注意

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

バージョン

この文章は2014年7月8日にリリースされたngx_memc v0.15 を説明します。

概要

# GET /foo?key=dog
#
# POST /foo?key=cat
# Cat's value...
#
# PUT /foo?key=bird
# Bird's value...
#
# DELETE /foo?key=Tiger
location /foo {
    set $memc_key $arg_key;

    # $memc_cmd defaults to get for GET,
    #   add for POST, set for PUT, and
    #   delete for the DELETE request method.

    memc_pass 127.0.0.1:11211;
}
# GET /bar?cmd=get&key=cat
#
# POST /bar?cmd=set&key=dog
# My value for the "dog" key...
#
# DELETE /bar?cmd=delete&key=dog
# GET /bar?cmd=delete&key=dog
location /bar {
    set $memc_cmd $arg_cmd;
    set $memc_key $arg_key;
    set $memc_flags $arg_flags; # defaults to 0
    set $memc_exptime $arg_exptime; # defaults to 0

    memc_pass 127.0.0.1:11211;
}
# GET /bar?cmd=get&key=cat
# GET /bar?cmd=set&key=dog&val=animal&flags=1234&exptime=2
# GET /bar?cmd=delete&key=dog
# GET /bar?cmd=flush_all
location /bar {
    set $memc_cmd $arg_cmd;
    set $memc_key $arg_key;
    set $memc_value $arg_val;
    set $memc_flags $arg_flags; # defaults to 0
    set $memc_exptime $arg_exptime; # defaults to 0

    memc_cmds_allowed get set add delete flush_all;

    memc_pass 127.0.0.1:11211;
}
http {
  ...
  upstream backend {
     server 127.0.0.1:11984;
     server 127.0.0.1:11985;
  }
  server {
      location /stats {
          set $memc_cmd stats;
          memc_pass backend;
      }
      ...
  }
}
...
# read the memcached flags into the Last-Modified header
# to respond 304 to conditional GET
location /memc {
    set $memc_key $arg_key;

    memc_pass 127.0.0.1:11984;

    memc_flags_to_last_modified on;
}
location /memc {
    set $memc_key foo;
    set $memc_cmd get;

    # access the unix domain socket listend by memcached
    memc_pass unix:/tmp/memcached.sock;
}

説明

このモジュールはほとんど全てのmemcached ascii プロトコルをサポートするために標準のmemcached モジュールを拡張します。

それによりmemcachedサーバに独自のRESTインタフェースを定義することができ、あるいはサブリクエストまたは independent fake requests <srlindsay/nginx-independent-subrequest>を使ってNGINXサーバ内からとても効率的な方法でmemcachedにアクセスすることができます。

楽しみのために(Cの)memcached応答パーサーを生成するためにRagelを使用したため、このモジュールはNGINXコアにマージされることはありそうにありません。

追加設定無しにlocationをキャッシュするためにこのモジュールを使うつもりであれば、そうするためにこのもジュールをSR Cache と一緒に試してください。

Luaと接続するために使われる場合は、lua-resty-memcached ライブラリがもっと柔軟でメモリの効率が良いため、このモジュールの代わりにそれを使うことをお勧めします。

memcachedサーバへのKeep-alive 接続

バックエンドのmemcachedサーバへのkeep-alive TCP接続のためには、このモジュールと一緒にhttp://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepaliveが必要です。

以下は例の設定です:

http {
  upstream backend {
    server 127.0.0.1:11211;

    # a pool with at most 1024 connections
    # and do not distinguish the servers:
    keepalive 1024;
  }

  server {
      ...
      location /memc {
          set $memc_cmd get;
          set $memc_key $arg_key;
          memc_pass backend;
      }
  }
}

どうやって動くか

upstream メカニズムに基づいて、全て自分自身でmemcached TCPプロトコルを実装します。I/Oに関する全てはブロックしません。

モジュール自身は他のupstreamモジュールと同じようにリクエスト間でupstream memcachedサーバへTCP接続を保持しません。動作の解決のために、memcachedサーバへのKeep-alive接続の章を見てください。

Memcached のコマンドがサポートされてます

memcachedのストレージコマンド set command, add command, replace command, prepend command および append command は、対応するmemcachedクエリを構築するために、キーとして $memc_key、有効期限(あるいは遅延)(デフォルトは0)として$memc_exptime、フラグ(デフォルトは0)として$memc_flags を使います。

もし$memc_value が全く定義されていない場合、リクエスト ボディはincr command および decr commandコマンドを除いて$memc_valueの値として使用されるでしょう。もし $memc_value が空の文字列 ("") として定義されている場合、空の文字列はそのままの値としてまだ使われるだろうことに注意してください。

以下のmemcachedコマンドは実装されテストされました(このモジュールによって定義される対応するNGINX変数でマークされたパラメータと一緒に):

get $memc_key

キーを使って値を取り出す。

location /foo {
    set $memc_cmd 'get';
    set $memc_key 'my_key';

    memc_pass 127.0.0.1:11211;

    add_header X-Memc-Flags $memc_flags;
}

キーが見つかった場合は応答ボディに値を入れて 200 OKを返し、そうでなければ404 Not Found を返します。flags 番号が $memc_flags 変数に設定されるので、標準のHttpHeadersModuleを使ってその情報を応答ヘッダに入れることがしばしば望まれます。

ERRORについては502,CLIENT_ERRORあるいは SERVER_ERRORを返します。

set $memc_key $memc_flags $memc_exptime $memc_value

リクエストボディをmemcachedの値として使用するには、$memc_value 変数を設定することだけを避けます。

# POST /foo
# my value...
location /foo {
    set $memc_cmd 'set';
    set $memc_key 'my_key';
    set $memc_flags 12345;
    set $memc_exptime 24;

    memc_pass 127.0.0.1:11211;
}

あるいは $memc_value がその値を保持するようにします:

location /foo {
    set $memc_cmd 'set';
    set $memc_key 'my_key';
    set $memc_flags 12345;
    set $memc_exptime 24;
    set $memc_value 'my_value';

    memc_pass 127.0.0.1:11211;
}

upstream memcached サーバが STOREDを返す場合は201 Createdを返し、NOT_STOREDには 200 を返し、NOT_FOUNDには404 を返し、ERROR,CLIENT_ERRORあるいは SERVER_ERRORには502 を返します。

オリジナルのmemcachedの応答は 404 NOT FOUNDを除いて応答ボディとして返されます。

add $memc_key $memc_flags $memc_exptime $memc_value

set commandに似ています。

replace $memc_key $memc_flags $memc_exptime $memc_value

set commandに似ています。

append $memc_key $memc_flags $memc_exptime $memc_value

set commandに似ています。

少なくともmemcachedバージョン1.2.2は"append"と”prepend"コマンドをサポートしないことに注意してください。少なくとも1.2.4以降のバージョンはこれら2つのコマンドをサポートします。

prepend $memc_key $memc_flags $memc_exptime $memc_value

append commandに似ています。

delete $memc_key

キーを使ってmemcachedエントリを削除します。

location /foo
    set $memc_cmd delete;
    set $memc_key my_key;

    memc_pass 127.0.0.1:11211;
}

削除が成功した場合は200 OKを返し、NOT_FOUNDには404 Not Found を返し、 ERROR, CLIENT_ERROR あるいはSERVER_ERRORには502 を返します。

オリジナルのmemcachedの応答は 404 NOT FOUNDを除いて応答ボディとして返されます。

delete $memc_key $memc_exptime

$memc_exptime変数によって指定される任意のexpiration 時間を受け付ける点を除いてdelete $memc_keyコマンドに似ています。

このコマンドは最新のmemcachedバージョン1.4.4ではもう利用できません。

incr $memc_key $memc_value

$memc_valueで指定された総数によって既存の $memc_keyの値を増加します:

location /foo {
    set $memc_key my_key;
    set $memc_value 2;
    memc_pass 127.0.0.1:11211;
}

前の例では、/fooにアクセスするたびにmy_keyの値を2ずつ増加するでしょう。

成功した場合は応答としてキーに関係新しい値と一緒に 200 OKを返します。あるいはキーが存在しない場合は404 Not Foundを返します。

ERRORについては502,CLIENT_ERRORあるいは SERVER_ERRORを返します。

decr $memc_key $memc_value

incr $memc_key $memc_valueに似ています。

flush_all

memcachedサーバ上の全てのキーを期限切れとしてマークします:

location /foo {
    set $memc_cmd flush_all;
    memc_pass 127.0.0.1:11211;
}

flush_all $memc_exptime

flush_all に似ていますが、$memc_exptime 変数で指定される期限切れの時間も受けつけます。

stats

memcachedサーバに一般的な目的の統計と設定を出力させます

location /foo {
    set $memc_cmd stats;
    memc_pass 127.0.0.1:11211;
}

リクエストが成功した場合は 200 OK を返し、そうでなければ ERROR, CLIENT_ERROR または SERVER_ERRORを返します。

upsteram のmemcachedサーバから出力されたrawの statsコマンドは応答ボディに配置されるでしょう。

バージョン

memcachedサーバのバージョン番号を質問します:

location /foo {
    set $memc_cmd version;
    memc_pass 127.0.0.1:11211;
}

リクエストが成功した場合は 200 OK を返し、そうでなければ ERROR, CLIENT_ERROR または SERVER_ERRORを返します。

upsteram のmemcachedサーバから出力されたrawの versionコマンドは応答ボディに配置されるでしょう。

ディレクティブ

NGINX 0.8.28の全てのmemcached module ディレクティブは memcached_memc_で置き換えたもので直接継承されます。例えば、memcached_pass ディレクティブはmemc_passと綴られます。

ここでは2つの最も重要なディレクティブのみを説明します(後者はこのモジュールで新しく導入されたディレクティブです)。

memc_pass

構文:memc_pass <memcached server IP address>:<memcached server port>
構文:memc_pass <memcached server hostname>:<memcached server port>
構文:memc_pass <upstream_backend_name>
構文:memc_pass unix:<path_to_unix_domain_socket>
デフォルト:none
コンテキスト:http, server, location, if
Phase:content

memcachedサーバのbackendを指定します。

memc_cmds_allowed

構文:memc_cmds_allowed <cmd>...
デフォルト:none
コンテキスト:http, server, location, if

アクセス可能なmemcachedコマンドをリスト化します。デフォルトでは、このモジュールでサポートされる全てのmemcachedコマンドがアクセス可能です。例としては、

location /foo {
    set $memc_cmd $arg_cmd;
    set $memc_key $arg_key;
    set $memc_value $arg_val;

    memc_pass 127.0.0.1:11211;

    memc_cmds_allowed get;
}

memc_flags_to_last_modified

構文:memc_flags_to_last_modified on|off
デフォルト:off
コンテキスト:http, server, location, if

memcachedフラグをepoch秒として読み込み、それを Last-Modified ヘッダの値として設定します。条件付きGETのために、NGINXに帯域を節約するために 304 Not Modified 応答を返すように合図を送ります。

memc_connect_timeout

構文:memc_connect_timeout <time>
デフォルト:60s
コンテキスト:http, server, location

memcachedサーバに接続するためのデフォルトで秒のタイムアウト。

混乱を避けるために常に明示的に時間単位を設定するのが懸命です。時間単位は“s”(seconds), “ms”(milliseconds), “y”(years), “M”(months), “w”(weeks), “d”(days), “h”(hours), and “m”(minutes) がサポートされます。

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

memc_send_timeout

構文:memc_send_timeout <time>
デフォルト:60s
コンテキスト:http, server, location

memcachedサーバにTCPリクエストを送信するためのデフォルトで秒のタイムアウト。

混乱を避けるために常に明示的に時間単位を設定するのが懸命です。時間単位は“s”(seconds), “ms”(milliseconds), “y”(years), “M”(months), “w”(weeks), “d”(days), “h”(hours), and “m”(minutes) がサポートされます。

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

memc_read_timeout

構文:memc_read_timeout <time>
デフォルト:60s
コンテキスト:http, server, location

memcachedサーバからTCP応答を受信するためのデフォルトで秒のタイムアウト。

混乱を避けるために常に明示的に時間単位を設定するのが懸命です。時間単位は“s”(seconds), “ms”(milliseconds), “y”(years), “M”(months), “w”(weeks), “d”(days), “h”(hours), and “m”(minutes) がサポートされます。

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

memc_buffer_size

構文:memc_buffer_size <size>
デフォルト:4k/8k
コンテキスト:http, server, location

このバッファサイズはメモリバッファを保持するために使われます。

  • the complete response for memcached commands other than get,
  • the complete response header (i.e., the first line of the response) for the get memcached command.

このデフォルトのサイズはページサイズで、おそらく4k あるいは 8k でうs。

memc_ignore_client_abort

構文:memc_ignore_client_abort on|off
デフォルト:off
コンテキスト:場所

クライアントが応答を待たずに接続を閉じたときに、memcacheサーバとの接続を閉じるかどうかを決定します。

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

インストール

(NGINXコアおよび他の多くの良いものと同じく)このモジュールをngx_openresty bundleを使ってインストールすることをお勧めします。ngx_openrestyのための インストールの段階 を見てください。

別のやり方として、このモジュールを手動で標準のNGINXソースディストリビューションの中にコンパイルすることができます:

例えば、バージョン1.7.2 (NGINX互換性を見てください)のNGINXのソースコードをnginx.orgからダウンロードし、このモジュールを使ってソースをビルドします:

wget 'http://nginx.org/download/nginx-1.7.2.tar.gz'
tar -xzvf nginx-1.7.2.tar.gz
cd nginx-1.7.2/

# Here we assume you would install you nginx under /opt/nginx/.
./configure --prefix=/opt/nginx \
    --add-module=/path/to/memc-nginx-module

make -j2
make install

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

開発者のため

memcached応答パーサはRagelによって生成されました。パーサーのCファイル、つまり src/ngx_http_memc_response.c、を再生成したい場合は、memcモジュールのソースツリーのルートから以下のコマンドを使用します:

$ ragel -G2 src/ngx_http_memc_response.rl

互換性

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

  • 1.7.x (最後のテスト: 1.7.2)
  • 1.5.x (最後のテスト: 1.5.12)
  • 1.4.x (最後のテスト: 1.4.4)
  • 1.2.x (最後のテスト: 1.2.9)
  • 1.1.x (最後のテスト: 1.1.5)
  • 1.0.x (最後のテスト: 1.0.10)
  • 0.9.x (最後のテスト: 0.9.4)
  • 0.8.x (最後のテスト: 0.8.54)
  • 0.7.x >= 0.7.46 (最後のテスト: 0.7.68)

It’s worth mentioning that some 0.7.x versions older than 0.7.46 might also work, but I can’t easily test them because the test suite makes extensive use of the HTTP Echo Module‘s echo_location directive, which requires at least NGINX 0.7.46 :)

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

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

コミュニティ

英語のメーリングリスト

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

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

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

バグのレポート

テストとコードの調整に多くの努力がされていますが、このモジュールのどこかにいくつかの深刻なバグが潜んでいるに違いありません。なんらかのおかしな動きがあった場合は、躊躇しないでください

  1. GitHubによって提供される issue tracking interface でチケットを作成する。
  2. あるいは、NGINX mailing listにバグレポート、あるいはパッチを送信します。

ソースリポジトリ

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

変更

このモジュールの各リリースの変更は、ngx_openresty バンドルのchange logsから取得することができます:

http://openresty.org/#Changes

テストスィート

このモジュールはPerl駆動テストスィートが付いています。test casesdeclarative です。Perl世界のTest::Baseモジュールに感謝します。

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

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

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

LWP::UserAgent あるいは IO::Socketのどちらか

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

テストスィートの実行前にlocalhost上の 11211 ポートでlistenしているmemcachedサーバも維持する必要があります。

テストスィートの幾つかの部分はNGINXをビルドする時にモジュール rewrite および HTTP Echoモジュール を有効にする必要があります。

TODO

  • memcachedコマンド cas, gets および stats $memc_value のサポートを追加。
  • noreply オプションのサポートを追加。

Getting involved

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

Author

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

このwikiページもauthor自身によって整備されており、同様に誰でもこのページを改善することは奨励されています。