
ユーザーが認証され、データにアクセスする権利があることを確認しながら、 phpのような重い言語を使用せずにキャッシュして配布したいデータがあるとします。 今日は、 nginx lua redis bundleを使用してこのタスクを完了し、サーバーから負荷を取り除き、サーバーによる情報転送の速度を数十倍にする方法を説明します。
まず、 nginx_lua_moduleモジュールでnginxをビルドする必要があります。
インストール手順
luaコンパイラーをインストールする(バージョン2.0または2.1)
luaJitをダウンロードして組み立てる
nginx開発キットを使用してnginxをビルドするには、 http_rewrite_moduleが必要です 。これには、 pcreライブラリが必要です。 したがって、それをインストールします
依存モジュールとnginx自体をダウンロードします
nginx開発キット
nginx luaモジュール
nginx
nginxを構成してインストールする
luaライブラリをダウンロードしてredis lua redis libを操作し、コマンドでluaライブラリフォルダーにコピーします
lua redisライブラリーをnginx構成に接続します
それだけです nginxによって実行されるスクリプトをluaで作成できるようになりました
luaJitをダウンロードして組み立てる
make && sudo make install
nginx開発キットを使用してnginxをビルドするには、 http_rewrite_moduleが必要です 。これには、 pcreライブラリが必要です。 したがって、それをインストールします
sudo apt-get update sudo apt-get install libpcre3 libpcre3-dev
依存モジュールとnginx自体をダウンロードします
nginx開発キット
nginx luaモジュール
nginx
nginxを構成してインストールする
export LUAJIT_LIB=/usr/local/lib // lua export LUAJIT_INC=/usr/local/include/luajit-2.1 // luaJit ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-ld-opt="-Wl,-rpath,/path/to/lua/lib" // Lua --add-module=/path/to/ngx_devel_kit // nginx devel kit --add-module=/path/to/lua-nginx-module // nginx lua module --without-http_gzip_module make -j2 sudo make install
luaライブラリをダウンロードしてredis lua redis libを操作し、コマンドでluaライブラリフォルダーにコピーします
sudo make install
lua redisライブラリーをnginx構成に接続します
http { ... lua_package_path lua_package_path "/path/to/lib/lua/resty/redis.lua;;"; // lua redis ... }
それだけです nginxによって実行されるスクリプトをluaで作成できるようになりました
キャッシュされたデータを迅速かつ効率的に返すために、キャッシュのウォームアップ時にすぐに最も頻繁に使用されるデータをredisに配置し、使用頻度の低いデータを要求に応じて配置します。 nginx側でluaを使用してデータを提供します。 Phpはこのバンドルに参加しません。これにより、データ出力が高速化され、サーバーのメモリ使用量が大幅に削減されます。
これを行うには、 Luaスクリプトを作成します
search.lua
local string = ngx.var.arg_string -- GET if string == nil then ngx.exec("/") -- , end local path = "/?string=" .. string local redis = require "resty.redis" -- redis local red = redis:new() red:set_timeout(1000) -- 1 sec local ok, err = red:connect("127.0.0.1", 6379) if not ok then ngx.exec(path) -- redis, end res, err = red:get("search:" .. string); -- redis if res == ngx.null then ngx.exec(path) -- , else ngx.header.content_type = 'application/json' ngx.say(res) -- , end
このファイルをnginx.confに含めてnginxをリロードします
location /search-by-string { content_by_lua_file lua/search.lua; }
さて、クエリ/ search-by-string?String = smthの場合、 luaは redisに接続し、 検索でデータを見つけようとします:smth key 。 データがない場合、リクエストはphpによって処理されます。 ただし、データがすでにキャッシュされており、 redisにある場合、すぐにユーザーに提供されます。
しかし、ユーザーが認証され、同時に特定の役割を持っている場合にのみデータを提供する必要がある場合はどうでしょうか?
この場合、セッションをredisに保存し、コンテンツを送信する前にセッションデータに従ってユーザーのロールを確認できます。
なぜなら 私はSymfony2フレームワークで作業しているため、小さなバンドルnginx-session-handlerがそのために作成されました。これを使用して、セッションをredisに正確に保存できます。
redisでは、データはハッシュ値として保存されます:
phpsession-セッションのキープレフィックス
php-session - phpセッション自体
user-role-ユーザーロール。
次に、このデータを処理するluaスクリプトを作成する必要があります。
session.lua
local redis = require "resty.redis" -- redis local red = redis:new() red:set_timeout(1000) -- 1 sec local ok, err = red:connect("127.0.0.1", 6379) if not ok then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) -- , end -- 500 local phpsession = ngx.var.cookie_PHPSESSID -- id cookie local ROLE_ADMIN = "ROLE_ADMIN" -- , if phpsession == ngx.null then ngx.exit(ngx.HTTP_FORBIDDEN) -- cookie ( ), end -- 403 local res, err = red:hget("phpsession:" .. phpsession, "user-role") -- -- redis id if res == ngx.null or res ~= ROLE_ADMIN then ngx.exit(ngx.HTTP_FORBIDDEN) -- ( ) end -- , , -- 403
CookieからユーザーのセッションIDを取得し、 HGET phpsession:id user-roleのリクエストでredisからセッションIDによってユーザーロールを取得しようとします。 ユーザーがセッションの有効期限が切れている場合、認証されていないか、ロールROLE_ADMINを持っていない場合、サーバーは403コードを返します。
このセッション処理スクリプトをデータ取得スクリプトの前に追加すると、ROLE_ADMINロールを持つ認証済みユーザーのみがデータを受信できるようになります。
実際、複数の場所nginxにはセッション処理スクリプトが必要になります。 別の場所に同じコードを記述しないために、必要な場所にこのファイルを接続します。
まず、セッション処理スクリプトを少し書き直しましょう。
session.lua
local _M = {} -- function _M.handle() -- local redis = require "resty.redis" local red = redis:new() red:set_timeout(1000) -- 1 sec local ok = red:connect("127.0.0.1", 6379) if not ok then ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end local phpsession = ngx.var.cookie_PHPSESSID local ROLE_ADMIN = "ROLE_ADMIN" if phpsession == ngx.null then ngx.exit(ngx.HTTP_FORBIDDEN) end local res = red:hget("phpsession:" .. phpsession, "user-role") if res == ngx.null or res ~= ROLE_ADMIN then ngx.exit(ngx.HTTP_FORBIDDEN) end end return _M --
ここで、 luaJitコンパイラーを使用してsession.luaからsession.oファイルを収集し、このファイルでnginxを収集する必要があります。
luaコンパイラーコマンドを実行して、session.oファイルをビルドします
/path/to/luajit/bin/luajit -bg session.lua session.o
nginxアセンブリの構成に行を追加します
--with-ld-opt="/path/to/session.o"
nginxのビルド(上記のnginxのビルド方法)
その後、ファイルを任意のluaスクリプトに接続し、handle()関数を呼び出してユーザーセッションを処理できます。
local session = require "session" session.handle()
最後に、比較のための小さなテスト。
コンピュータ構成
プロセッサー:Intel Xeon CPU X3440 @ 2.53GHz×8
メモリ:7.9 GiB
メモリ:7.9 GiB
Redisからphpまたはluaデータを取得するテスト
ab -n 100 -c 100 php
サーバーソフトウェア:nginx / 1.9.4
同時実行レベル:100
テストにかかった時間:3.869秒
完全なリクエスト:100
失敗したリクエスト:0
1秒あたりのリクエスト:25.85 [#/秒](平均)
リクエストあたりの時間:3868.776 [ms](平均)
リクエストごとの時間:38.688 [ms](平均、すべての同時リクエスト全体)
転送速度:6.66 [Kバイト/秒]受信
接続時間(ミリ秒)
最小平均[±sd]最大中央値
接続:1 3 1.1 3 5
処理:155 2116 1053.7 2191 3863
待機中:155 2116 1053.7 2191 3863
合計:160 2119 1052.6 2194 3864
特定の時間内に処理されたリクエストの割合(ミリ秒)
50%2194
66%2697
75%3015
80%3159
90%3504
95%3684
98%3861
99%3864
100%3864(最長リクエスト)
同時実行レベル:100
テストにかかった時間:3.869秒
完全なリクエスト:100
失敗したリクエスト:0
1秒あたりのリクエスト:25.85 [#/秒](平均)
リクエストあたりの時間:3868.776 [ms](平均)
リクエストごとの時間:38.688 [ms](平均、すべての同時リクエスト全体)
転送速度:6.66 [Kバイト/秒]受信
接続時間(ミリ秒)
最小平均[±sd]最大中央値
接続:1 3 1.1 3 5
処理:155 2116 1053.7 2191 3863
待機中:155 2116 1053.7 2191 3863
合計:160 2119 1052.6 2194 3864
特定の時間内に処理されたリクエストの割合(ミリ秒)
50%2194
66%2697
75%3015
80%3159
90%3504
95%3684
98%3861
99%3864
100%3864(最長リクエスト)
ab -n 100 -c 100 lua
サーバーソフトウェア:nginx / 1.9.4
同時実行レベル:100
テストにかかった時間:0.022秒
完全なリクエスト:100
失敗したリクエスト:0
1秒あたりのリクエスト:4549.59 [#/ sec](平均)
リクエストあたりの時間:21.980 [ms](平均)
リクエストごとの時間:0.220 [ms](平均、すべての同時リクエスト全体)
転送速度:688.66 [Kバイト/秒]受信
接続時間(ミリ秒)
最小平均[±sd]最大中央値
接続:2 4 0.9 4 6
処理:3 13 1.6 13 14
待機中:3 13 1.6 13 14
合計:9 17 1.3 18 18
特定の時間内に処理されたリクエストの割合(ミリ秒)
50%18
66%18
75%18
80%18
90%18
95%18
98%18
99%18
100%18(最長リクエスト)
同時実行レベル:100
テストにかかった時間:0.022秒
完全なリクエスト:100
失敗したリクエスト:0
1秒あたりのリクエスト:4549.59 [#/ sec](平均)
リクエストあたりの時間:21.980 [ms](平均)
リクエストごとの時間:0.220 [ms](平均、すべての同時リクエスト全体)
転送速度:688.66 [Kバイト/秒]受信
接続時間(ミリ秒)
最小平均[±sd]最大中央値
接続:2 4 0.9 4 6
処理:3 13 1.6 13 14
待機中:3 13 1.6 13 14
合計:9 17 1.3 18 18
特定の時間内に処理されたリクエストの割合(ミリ秒)
50%18
66%18
75%18
80%18
90%18
95%18
98%18
99%18
100%18(最長リクエスト)
1秒あたりのリクエスト数の差は175倍です。
他のパラメーターを使用した同じテスト
ab -n 10000 -c 100 php
サーバーソフトウェア:nginx / 1.9.4
同時実行レベル:100
テストにかかった時間:343.082秒
完全なリクエスト:10000
失敗したリクエスト:0
1秒あたりのリクエスト:29.15 [#/ sec](平均)
リクエストあたりの時間:3430.821 [ms](平均)
リクエストあたりの時間:34.308 [ms](平均、すべての同時リクエスト全体)
転送速度:7.51 [キロバイト/秒]受信
接続時間(ミリ秒)
最小平均[±sd]最大中央値
接続:0 0 0.3 0 4
処理:167 3414 197.5 3408 4054
待機中:167 3413 197.5 3408 4054
合計:171 3414 197.3 3408 4055
特定の時間内に処理されたリクエストの割合(ミリ秒)
50%3408
66%3438
75%3458
80%3474
90%3533
95%3633
98%3714
99%3866
100%4055(最長リクエスト)
同時実行レベル:100
テストにかかった時間:343.082秒
完全なリクエスト:10000
失敗したリクエスト:0
1秒あたりのリクエスト:29.15 [#/ sec](平均)
リクエストあたりの時間:3430.821 [ms](平均)
リクエストあたりの時間:34.308 [ms](平均、すべての同時リクエスト全体)
転送速度:7.51 [キロバイト/秒]受信
接続時間(ミリ秒)
最小平均[±sd]最大中央値
接続:0 0 0.3 0 4
処理:167 3414 197.5 3408 4054
待機中:167 3413 197.5 3408 4054
合計:171 3414 197.3 3408 4055
特定の時間内に処理されたリクエストの割合(ミリ秒)
50%3408
66%3438
75%3458
80%3474
90%3533
95%3633
98%3714
99%3866
100%4055(最長リクエスト)
ab -n 10000 -c 100 lua
サーバーソフトウェア:nginx / 1.9.4
同時実行レベル:100
テストにかかった時間:0.899秒
完全なリクエスト:10000
失敗したリクエスト:0
1秒あたりのリクエスト:11118.29 [#/秒](平均)
リクエストあたりの時間:8.994 [ms](平均)
リクエストあたりの時間:0.090 [ms](平均、すべての同時リクエスト全体)
転送速度:1682.94 [Kバイト/秒]受信
接続時間(ミリ秒)
最小平均[±sd]最大中央値
接続:0 0 0.4 0 5
処理中:1 9 3.4 7 19
待機中:1 9 3.5 7 18
合計:2 9 3.4 7 21
特定の時間内に処理されたリクエストの割合(ミリ秒)
50%7
66%13
75%13
80%13
90%13
95%13
98%13
99%15
100%21(最長リクエスト)
同時実行レベル:100
テストにかかった時間:0.899秒
完全なリクエスト:10000
失敗したリクエスト:0
1秒あたりのリクエスト:11118.29 [#/秒](平均)
リクエストあたりの時間:8.994 [ms](平均)
リクエストあたりの時間:0.090 [ms](平均、すべての同時リクエスト全体)
転送速度:1682.94 [Kバイト/秒]受信
接続時間(ミリ秒)
最小平均[±sd]最大中央値
接続:0 0 0.4 0 5
処理中:1 9 3.4 7 19
待機中:1 9 3.5 7 18
合計:2 9 3.4 7 21
特定の時間内に処理されたリクエストの割合(ミリ秒)
50%7
66%13
75%13
80%13
90%13
95%13
98%13
99%15
100%21(最長リクエスト)
1秒あたりのリクエスト数の差は381回です。
私の記事がお役に立てば幸いです。 あなたが提案、コメントを持っているか、より良い方法を知っているなら-書いてください。