nginx-lua-moduleでLuaスクリプト書いてみた
プロダクトでWebサーバ上の現在時刻出したい要件がありました。
これぐらいの処理ならアプリケーション介さずともnginxだけでやりたいですね。
現在時刻ヘッダーにつけるならnginx標準機能で出来そうなんですが、
深淵なる理由からコンテンツとして欲しいとのこと。
今後、Nginx+Lua試してみたいなーという要件もありましたし、
せっかくなのでこの機能をLuaスクリプトで書いてみることにしました。
nginxレシピ
opscodeのnginxクックブックにはluaをインストールするレシピもありました。
しかし、例のごとくそのままでは動かせなかったので
一部オーバーライドしたクックブックを書いてみました。
AWSの生AMIにこれをそのままプロビジョニングするとNginx+Luaが起動することを確認しています。
https://github.com/toritori0318/chef-nginx-lua-sample
直したところ
recipes/lua.rbにパッチを当てたのと、
recipes/source.rbにluaをインストールする処理を差し込んだくらいです。
ちなみにcjsonを入れているのは、今回json形式でレスポンスさせたかったからです。
Luaを動かすだけであればcjsonを入れる必要はありません。
サンプルアプリ仕様
サンプル実装
/etc/nginx/sites-available/lua_current_time
nginxのコンフィグです。
特に語るところはありません。
# Lua soライブラリのパス指定。今回はcjsonのため(ファイルパターンも指定が必要らしい) lua_package_cpath "/usr/local/lib/lua/5.1/?.so"; server { listen 80; access_log /var/log/nginx/access.log; location /current_time { # 外部Luaスクリプト読み込み content_by_lua_file /etc/nginx/lua/current_time.lua; } location / { default_type 'text/plain'; # コードもそのまま書ける content_by_lua "ngx.say('Hello,lua!')"; } }
/etc/nginx/lua/current_time.lua
パラメータを受け取ってゴニョゴニョしています。
特に語るところはありません。
local cjson = require "cjson" local ctime = "" local args = ngx.req.get_uri_args() if args.df == "epoch" then ctime = os.date("%s") else ctime = os.date("%Y-%m-%dT%H:%M:%S %z") end if args.rf == "json" then ngx.header.content_type = "application/json"; ngx.print(cjson.encode({current_time = ctime})) else ngx.header.content_type = "text/plain"; ngx.print(ctime) end
非常に簡単ですね。
ベンチマーク
abしてみました。
コマンドパラメータはこんな感じです。
ab -n 20000 -c 2 http://127.0.0.1/xxxx
/ (Hello Lua)
Server Software: nginx/1.4.3 Server Hostname: 127.0.0.1 Server Port: 80 Document Path: / Document Length: 11 bytes Concurrency Level: 2 Time taken for tests: 2.018 seconds Complete requests: 20000 Failed requests: 0 Write errors: 0 Total transferred: 3060000 bytes HTML transferred: 220000 bytes Requests per second: 9912.15 [#/sec] (mean) Time per request: 0.202 [ms] (mean) Time per request: 0.101 [ms] (mean, across all concurrent requests) Transfer rate: 1481.02 [Kbytes/sec] received
/current_time
Server Software: nginx/1.4.3 Server Hostname: 127.0.0.1 Server Port: 80 Document Path: /current_time Document Length: 25 bytes Concurrency Level: 2 Time taken for tests: 2.339 seconds Complete requests: 20000 Failed requests: 0 Write errors: 0 Total transferred: 3340000 bytes HTML transferred: 500000 bytes Requests per second: 8549.87 [#/sec] (mean) Time per request: 0.234 [ms] (mean) Time per request: 0.117 [ms] (mean, across all concurrent requests) Transfer rate: 1394.36 [Kbytes/sec] received
/static/index.html(静的ファイル配信。このファイルは手動で作りました)
Server Software: nginx/1.4.3 Server Hostname: 127.0.0.1 Server Port: 80 Document Path: /static/index.html Document Length: 6 bytes Concurrency Level: 2 Time taken for tests: 1.942 seconds Complete requests: 20000 Failed requests: 0 Write errors: 0 Total transferred: 4680000 bytes HTML transferred: 120000 bytes Requests per second: 10298.39 [#/sec] (mean) Time per request: 0.194 [ms] (mean) Time per request: 0.097 [ms] (mean, across all concurrent requests) Transfer rate: 2353.34 [Kbytes/sec] received
静的ファイル配信よりわずかに落ちますが十分早い。
Nginx+Lua、環境設定が若干面倒ですが、
上記クックブックを使うと一発で環境作れますし、
Luaスクリプトもお手軽に書けそうなので試してみてはいかがでしょうか〜
(゚Д゚)オLua!オLua!
*1:※追記 openrestyを使うと楽できるようです! http://openresty.org/