この記事は主に、ngx_lua を介してバックエンドの memcached および redis とノンブロッキングで通信する方法に焦点を当てています。
1. Memcached
Nginx で Memcached にアクセスするには、モジュールのサポートが必要です。このモジュールは、バックエンド Memcached とのノンブロッキング通信を実行できます。 Memcached が公式に提供されているのは、このモジュールが get 操作のみをサポートしているのに対し、Memc はほとんどの Memcached コマンドをサポートしていることです。 mEMCモジュールにパラメーターとして入力変数を転送する。 memc_pass はバックエンド Memcached サーバーを指します。
構成:
[プレーン]ビュー
普通のコピープリント?
- #HttpMemcModuleを使用する
location = /memc { set $memc_cmd $arg_cmd -
set $memc_key $ arg_key; $memc_value $arg_val を設定します。 -
set $memc_exptime $arg_exptime;
-
-
memc_pass '127.0.0.1:11211'
}
- ;
[プレーン]ビュー
普通のコピープリント?
$カール 'http://localhost/memc?cmd=set&key=foo&val=Hello'
- $ 保存されました $カール 'http://localhost/memc?cmd=get&key =foo'
-
$ こんにちは
これでmemcachedへのアクセスが実現します。 luaでmemcachedにアクセスする方法を見てみましょう。 -
構成:
[プレーン]ビュー
普通のコピープリント?
#Lua で Memcached にアクセス
- location = /memc { Internal; #内部アクセスのみ
-
set $memc_cmd get;
- $memc_key $ arg_key を設定します。
- memc_pass '127.0.0.1:11211';
- }
- location = /lua_memc {
- content_by_lua '
- ローカル res = ngx.location.capture("/ memc" , {
- args = { key = ngx.var.arg_key }
- })
- if res.status == 200 then
-
ngx.say(res.body)
- 終わり
普通のコピープリント?
$カール「http://localhost/lua_memc?key=foo」
- $こんにちは
-
Lua を介した memcached へのアクセスは、主に関数呼び出しと同様のメソッドのサブリクエストを通じて実装されます。まず、バックエンド memcached を介した通信用に memc の場所が定義されます。これは memcached ストレージに相当します。 Memc モジュール全体がノンブロッキングであるため、ngx.location.capture もノンブロッキングであり、操作全体がノンブロッキングです。
2. Redis
Redis にアクセスするには、非ブロッキング方式で Redis と通信できる HttpRedis2Module のサポートが必要です。ただし、redis2 の応答は redis のネイティブな応答であるため、Lua で使用する場合は、この応答を解析する必要があります。 LuaRedisModule を使用すると、redis のネイティブ リクエストを構築し、redis のネイティブ レスポンスを解析できます。
構成:
[プレーン]ビュー
普通のコピープリント?
- #Lua で Redis にアクセス
- location = /redis {
- Internal; #内部アクセスのみ
- redis2 _query get $arg_key
- redis2_pass '127.0. :6379';
- }
- location = /lua_redis { #LuaRedisParser が必要です
- content_by_lua '
- ローカルパーサー = require("redis.parser")
- ローカル解像度 = ngx .location.capture("/redis", {
- args = { key = ngx.var.arg_key }
- })
- if res.status == 200 then
- Reply = parser.parse_reply(res.body)
- ngx.say(reply)
- end
- '; 出力:
- [プレーン]ビュー
普通のコピープリント?
$curl 'http://localhost/lua_redis?key=foo'
$ こんにちは
-
memcached へのアクセスと同様に、Redis のクエリ専用の Redis ストレージを提供する必要があります。次に、サブリクエストを通じて redis を呼び出します。 3. Redis パイプライン
- 実際に Redis にアクセスする場合、複数のキーを同時にクエリする必要がある場合があります。 ngx.location.capture_multi を使用して複数のサブリクエストを Redis ストレージに送信し、応答の内容を解析できます。ただし、Nginx カーネルには、一度に開始できるサブリクエストの数が 50 を超えることができないと規定されているため、キーの数が 50 を超えると、この解決策は適用できなくなります。 幸いなことに、redis は 1 つの接続で複数のコマンドを実行できるパイプライン メカニズムを提供しており、これによりコマンドを複数回実行する往復遅延を削減できます。クライアントがパイプライン経由で複数のコマンドを送信すると、redis はこれらのコマンドを順番に受信して実行し、コマンドの結果を順番に出力します。 Lua でパイプラインを使用する場合、redis2 モジュールの redis2_raw_queries を使用して、redis のネイティブ リクエスト クエリを実行する必要があります。
構成: [プレーン]ビュー
普通のコピープリント?
- #Lua で Redis にアクセス
- location = /redis {
- Internal; #内部アクセスのみ
-
- redis2_raw_queries $args $ echo_request_body;
- redis2_pass '127.0 .0.1:6379';
-
- location = /pipeline {
-
content_by_lua 'conf/pipeline. }
パイプライン .lua [プレーン]ビュー
普通のコピープリント?
- conf/pipeline.lua file }, {'get', 'two'}
} - -- ネイティブ Redis クエリを構築し、onernget twon を取得します
- local raw_reqs = {}
- for i , req in ipairs ( reqs) do
- table.insert(raw_reqs, parser.build_query(req))
- end
- local res = ngx.location.capture('/redis?'..#reqs, { body = table.concat(raw_reqs, '') })
-
- if res.status と res.body then
- -- Redis のネイティブ応答を解析します
ローカル 応答 = パーサー。 parse_replies(res.body, #reqs) for i, Reply in ipairs(replies) do ngx.say(reply[1]) -
End - 出力:で] ビュー
普通のコピープリント?
-
$curl 'http://localhost/pipeline'
$ first Second
- 4. Redis と memcached にアクセスする前述の例では、毎回リクエストが処理され、バックエンド サーバーとの接続が確立され、リクエストの処理後に接続が解放されます。このプロセスでは、3 回のハンドシェイクや待機時間などのオーバーヘッドが発生しますが、これは同時実行性の高いアプリケーションでは耐えられません。このオーバーヘッドを排除するために、ここでは接続プールが導入されています。 接続プールには、HttpUpstreamKeepaliveModule モジュールのサポートが必要です。
- 構成:
[プレーン]ビュー
普通のコピープリント?
- Http {##httpupstreamKeepaliveModuleが必要です
- アップストリームredis_pool {
- サーバー127.0.0.1:6379;
- #1024の接続されたコネクタに対応できます
- 1024 シングル;
サーバー { local =/redis { ... redis2_pass redis_pool -
}
- ;
このモジュールはキープアライブ命令を提供し、そのコンテキストは次のとおりです。上流の。 Nginx をリバース プロキシとして使用する場合、アップストリームが使用されることがわかります。実際には、この「アップストリーム」は、redis、memcached、mysql などのサーバーを指します。アップストリームは仮想サーバー クラスターを定義でき、これらのバックエンド サーバーは負荷分散を利用できます。キープアライブ 1024 は接続プールのサイズを定義します。接続数がこのサイズを超えると、後続の接続は自動的に短い接続に縮退します。接続プールの使用は非常に簡単で、元の IP とポート番号を置き換えるだけです。 - ある人は、接続プールを使用せずに (以前の Memc モジュールを使用して) memcached にアクセスしたときの RPS が 20,000 であることを測定しました。接続プールを使用した後、rps は 140,000 まで上昇しました。実際の状況では、それほど大きな改善は達成できないかもしれませんが、基本的には 100 ~ 200% の改善は可能です。
- 5. まとめ memcached と redis へのアクセスについてまとめます。
- 1. Nginx は強力なプログラミング モデルを提供します。location は関数に相当し、サブリクエストは関数呼び出しに相当し、location はサブリクエストを自分自身に送信することもできるため、再帰的モデルが形成されるため、このモデルが使用されます。複雑なビジネスロジックを実装します。 2. Nginx の IO 操作はノンブロッキングである必要があります。Nginx がそこでブロックすると、Nginx のパフォーマンスが大幅に低下します。したがって、Lua では、これらの IO 操作を Nginx のイベント モデルに委任するために、ngx.location.capture を通じてサブリクエストを発行する必要があります。
- 3. TCP 接続を使用する必要がある場合は、接続プールを使用してみてください。これにより、接続の確立と解放における多くのオーバーヘッドが排除されます。
上記は、内容の側面も含めて、ngx_lua を使用して高同時実行性のアプリケーションを構築する方法を紹介しています。PHP チュートリアルに興味のある友人に役立つことを願っています。