私の専門的な変形により、次のケースを検討します。
- アクセスを制限したいWebリソースがあります。
- リソース自体は変更できないか、非常に望ましくありません。
このタスクにアプローチする方法は?
ユーザーの権利を確認するリソースの前にゲートウェイを配置してみましょう。チェックの結果に応じて、ユーザーにリソースへのアクセスを許可するかどうかを設定します。 ユーザー権限はTarantoolに保存されます。 マスターとマスターのレプリケーションがあり、ゲートウェイのクラスターを構築する必要がある場合に便利です。 NGINXをゲートウェイの基礎として使用します(Webサーバーを自分で記述しないでください...)。
NGINXは、「インテリジェンス」を追加して、ユーザーがどこに行くことができ、どこに行かないかを理解する必要があります。 これにはngx_http_auth_request_moduleを使用できますが、これをTarantoolと組み合わせる方法は明確ではありません。 OpenRestyの例を見てみましょう。Lua、つまりlua-nginx-moduleを使用して、ゲートウェイを知的化します。
NGINX内からTarantoolにアクセスするには、選択した言語の適切なドライバー、または「コネクター」が必要です。 Tarantoolの著者自身が、LuaからTarantoolへのコネクタが必要な場合は、アーキテクチャに何か問題があると書いています。 しかし、NGINX + Luaバンドルの場合、これは正当化される可能性があります。
グーグルは、最大3つの候補者の存在を示しています。
- github.com/ziontab/lua-nginx-tarantool-nginxコソケットに実装されています。 真実は長い間更新されていません。
- github.com/tarantool/tarantool-luaは、Tarantool開発者の公式ドライバーです。 これは、最初の候補の修正されたフォークです。 nginxコソケットに加えて、通常のLuaソケットをサポートしています。
- github.com/perusio/lua-resty-tarantool-コミットなしの2年間、Tarantool 1.7プロシージャコールのセマンティクスのサポートはありません。
何を選ぶ? テストする必要があります。 それはします。
テストスタンド:
負荷ジェネレーターから、要求は安全な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)は明らかにリーダーであるだけでなく、生産における唯一のユースケースです。 また、実際のプロジェクトで特定のテクノロジーを使用するかどうかを決定する前に、さまざまなユースケースをテストする必要があると確信しました。