NGINXのTarantool用Luaコネクタの比較ストレステスト

最近、HaranにはTarantoolについての非常に多くの記事が掲載されています。データベースとアプリケーションサーバーは、さまざまな興味深いプロジェクトでMail.Ru Group、Avito、Yotaによって使用されています。 だから、私は思った-なぜ私たちは悪化していますか? それも試してみましょう。



私の専門的な変形により、次のケースを検討します。





このタスクにアプローチする方法は?



ユーザーの権利を確認するリソースの前にゲートウェイを配置してみましょう。チェックの結果に応じて、ユーザーにリソースへのアクセスを許可するかどうかを設定します。 ユーザー権限はTarantoolに保存されます。 マスターとマスターのレプリケーションがあり、ゲートウェイのクラスターを構築する必要がある場合に便利です。 NGINXをゲートウェイの基礎として使用します(Webサーバーを自分で記述しないでください...)。



NGINXは、「インテリジェンス」を追加して、ユーザーがどこに行くことができ、どこに行かないかを理解する必要があります。 これにはngx_http_auth_request_moduleを使用できますが、これをTarantoolと組み合わせる方法は明確ではありません。 OpenRestyの例を見てみましょう。Lua、つまりlua-nginx-moduleを使用して、ゲートウェイを知的化します。



NGINX内からTarantoolにアクセスするには、選択した言語の適切なドライバー、または「コネクター」が必要です。 Tarantoolの著者自身が、LuaからTarantoolへのコネクタが必要な場合は、アーキテクチャに何か問題があると書いています。 しかし、NGINX + Luaバンドルの場合、これは正当化される可能性があります。



グーグルは、最大3つの候補者の存在を示しています。





何を選ぶ? テストする必要があります。 それはします。



テストスタンド:







負荷ジェネレーターから、要求は安全なTLS形式でゲートウェイに送信されます(専門的な変形を忘れないでください)。 次に、NGINXはTLSを削除し、プレーンHTTPの形式で保護されたリソースに渡します。



試験機の機能



マシンと保護されたリソースの読み込み



(2台の同一の車)

CPU 2xIntel Xeon E5 2680 @ 2.70GHz Sandy Bridge-EP / EX 32nm Technology 8コア/ 16スレッド
RAM 32.0GB DDR3 @ 799MHz(11-11-11-28)
MB Supermicro X9DR3-F
ディスク 223GB OCZ-VERTEX3(SSD)
OS Debian 8.9 x64(カーネル3.16.39-1)
Nginx 1.12.1
仕事 4.0.2-dirty [epoll] + GOST TLSパッチ

ゲートウェイ

CPU 1 vCPU
RAM 8 GB
プラットフォーム VMWare Workstation 12.5
ホストCPU Intel Core i5 7600K 3.8 GHz
ホストRAM 16 GB
ホストOS Windows 10 x64
Nginx 1.12.1
lua-nginx-module 最新のマスターブランチ


NGINX保護されたリソースの構成



珍しいことはありません-空のGIFだけです。



user nginx; worker_processes 32; error_log /var/log/ngate/nginx/error.log warn; pid /var/run/nginx.pid; worker_rlimit_nofile 65535; events { worker_connections 8192; } http { access_log /var/log/ngate/nginx/access.log main; keepalive_timeout 65; server { listen 80; server_name fast-ipsec2-db8; location / { root /var/www; index index.html index.htm; } location = /ff/empty_gif.gif { empty_gif; } } # end server }
      
      





ゲートウェイNGINX構成:



 worker_processes 1; error_log /var/log/nginx/error.log warn; worker_rlimit_nofile 65535; events { worker_connections 8192; } http { include /etc/opt/nginx/mime.types; default_type text/html; sendfile on; keepalive_timeout 65; autoindex off; server_tokens off; lua_package_path '?.lua;/opt/lua/?.lua;'; # HTTPS server server { listen 443 ssl; server_name perf-test-1; ssl_certificate www.example.com.crt; ssl_certificate_key www.example.com.key; ssl_protocols TLSv1; ssl_ciphers HIGH:!aNULL:!MD5; if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 444; } # Local Tarantool Node set $ng_local_tnt_addr '127.0.0.1'; set $ng_local_tnt_port 3320; # ff location /ff/ { proxy_pass http://fast-ipsec2-db8/ff/; access_by_lua_file /opt/lua/res_access.lua; } } # end server perf-test-1 } # end http
      
      





次の行に注意してください。



 access_by_lua_file /opt/lua/res_access.lua;
      
      





ここでユーザーの権利を確認します。



コード/opt/lua/res_access.lua



簡単です:



1.認証Cookieを抽出します。

2.ユーザーがアクセスしているリソースを理解するためのParsim要求。

3.受け取ったTarantoolの値を渡して、判断を下します-ユーザーに任せるかどうかを決めます。

4.タランツールの回答を処理します

5.応答に応じて、ユーザーを開始するか、「アクセス拒否」と発声します。

簡単にするために、記事の範囲外のアクセス権を仕事に任せ、常にユーザーにリソースを許可します。



 local auth_cookie_value = ngx.var.cookie_nginxauth if auth_cookie_value == nil then ngx.log(ngx.WARN, "Authentication cookie not provided.") ngx.exit(ngx.HTTP_NOT_FOUND) end local uri_root_regex = "(\\/[a-zA-Z0-9\\-\\._]+\\/)" local m, err = ngx.re.match(ngx.var.uri, uri_root_regex, "ai") if err then ngx.log(ngx.ERR, "Error in regexp: ", err) ngx.exit(ngx.HTTP_NOT_FOUND) end if m == nil then ngx.log(ngx.ERR, "Regexp returned nil value.") ngx.exit(ngx.HTTP_NOT_FOUND) end local uri_root = m[0] if uri_root == nil then ngx.log(ngx.ERR, "error in regexp") ngx.exit(ngx.HTTP_NOT_FOUND) end local tnt = require 'resty.tarantool' #local tnt = require 'tarantool-lua.tarantool' local tar, err = tnt:new({ host = ngx.var.ng_local_tnt_addr, port = ngx.var.ng_local_tnt_port, --Default value 2000 socket_timeout = 500, # connect_now = false, }) if not tar:connect() then ngx.log(ngx.ERR, "TNT connection failed.") ngx.exit(ngx.HTTP_NOT_FOUND) end local res, err = tar:call('check_access', {auth_cookie_value, uri_root}) if not tar:set_keepalive() then ngx.log(ngx.WARN, "TNT connection not set as keep-alive.") end if not res then ngx.log(ngx.ERR, "TNT call failed: " .. err) ngx.exit(ngx.HTTP_NOT_FOUND) end if res[1] ~= nil and res[1][1] == true then -- Access granted ngx.log(ngx.INFO, "Resource access granted: " .. uri_root) return else ngx.log(ngx.ERR, "Resource access denied: " .. uri_root) ngx.exit(ngx.HTTP_FORBIDDEN) end
      
      





Tarantoolストアドプロシージャコード



許可Cookieは引き続き無視されるため、簡単にするために取得および形成のプロセスは考慮しません。



 local strict = require('strict') strict.on() function check_access(session_id, resource_name) if session_id == nil or resource_name == nil then return false end log.info('Access to resource ' .. resource_name .. ' granted.') return true end
      
      





テスト方法



テストには、wrkユーティリティを使用します。 負荷テストで実証されており、TLSに加えて、Luaでスクリプトをサポートしています(ただし、現在は使用しません)。 機能のうち、wrkには切断不可能なTLSセッション再開機能があるため、ゲートウェイCPUは永続的なTLSハンドシェイクに浪費されません。 スループットではなく、1秒あたりのアクセス制御チェックのパフォーマンスをテストするために、保護されたリソースから最小サイズのファイル(43バイトを使用する空のGIF)を要求します。



テストを始めましょう。



候補1(lua-nginx-tarantool):



まったく機能しません。 ドキュメントに従って使用する場合は、



 local tnt = require 'lua-nginx-tarantool.tarantool' local tar, err = tnt:new({...})
      
      





エラーが表示されます:



 runtime error: /opt/lua/res_access.lua:33: attempt to index local 'tnt' (a boolean value)
      
      





わかりません。



候補2(tarantool-lua):



 ./wrk -t32 -c32 -d30s --latency --timeout 10s -H "Host: perf-test-1" -H "Cookie: nginxauth=XXX " https://192.168.85.159/ff/empty_gif.gif Thread Stats Avg Stdev Max +/- Stdev Latency 252.12ms 248.32ms 514.22ms 31.13% Req/Sec 4.55 5.54 60.00 95.77% Latency Distribution 50% 21.75ms 75% 502.22ms 90% 503.61ms 99% 507.63ms 3767 requests in 30.04s, 1.33MB read Non-2xx or 3xx responses: 1868 Requests/sec: 125.40 Transfer/sec: 45.49KB
      
      





まず、それだけでは不十分です。 1秒あたり125クエリのみ。



第二に-回答の半分以上-予想される200ではなく、何か他のもの。 これは何? 答えはerror_log NGIXNにあります。



 [error] 11856#0: *23410 [lua] res_access.lua:42: TNT connection failed.
      
      





何かがおかしい-Tarantoolが接続を拒否するか、NGINXがそれらを消化できません。

しかし、もう一度試してください。



候補3(lua-resty-tarantool):



 ./wrk -t32 -c32 -d30s --latency --timeout 10s -H "Host: perf-test-1" -H "Cookie: nginxauth=XXX " https://192.168.85.159/ff/empty_gif.gif Thread Stats Avg Stdev Max +/- Stdev Latency 9.03ms 1.13ms 28.79ms 79.90% Req/Sec 110.13 10.43 131.00 75.49% Latency Distribution 50% 8.63ms 75% 9.46ms 90% 10.64ms 99% 11.81ms 105344 requests in 30.03s, 43.40MB read Requests/sec: 3508.50 Transfer/sec: 1.45MB
      
      





わあ! 1秒あたり3500リクエストであり、単一のエラーではありません!

また、error_logでは、NGINXは無音です。



結論



彼の由緒ある年齢といくつかの欠点にもかかわらず、Candidate 3(lua-resty-tarantool)は明らかにリーダーであるだけでなく、生産における唯一のユースケースです。 また、実際のプロジェクトで特定のテクノロジーを使用するかどうかを決定する前に、さまざまなユースケースをテストする必要があると確信しました。



All Articles