こんにちは。ユナイテッドの技術開発部で部長をしている伊良子です。
ユナイテッドでのアドサーバ開発では、Go, Lua, C言語(nginxモジュール)が主に使われる言語ですが、ここ1年ほどで急速にGoを利用するケースが増えています。新規でNginxのCモジュールを開発することはここ数年では皆無ですし、Luaで書かれているアドサーバをGoにリプレースするケースも出てきている状況です。最近ですと、数年前に私がLua+C言語で書いた弊社DSP『Bypass』のRTB入札サーバも、今ではGoに完全にリプレースされており、Luaが大好きだった私としては少々寂しいところです。 しかしながら、保守性の高さからLuaを選択するアドバンテージは高いですし、また速度面でも(弊社内でのベンチマークではありますが)シンプルな処理であるほどLuaが勝るケースが多いため、シンプルなAPIサーバなど、利用の用途はまだまだあると考えています。
今回は、Luaを利用する上で、便利なモジュールを幾つかご紹介したいと思います。
lsyslog
https://github.com/remakeelectric/lsyslog
Luaからsyslogを使うラッパーモジュールです。C言語でコンパイルされたモジュールなので高速に動作しますし、rsyslogの設定と連携することでカスタムされたログを安定的に出力することが可能です。設定も簡単です。
一例として、Luaのサンプルコードと、それに対応したrsyslogの設定を下記します。
1 2 3 4 5 6 7 8 9 10 11 12 |
local syslog = require "syslog" 中略 -- output syslog syslog.openlog("test_system", syslog.LOG_ODELAY, "LOG_USER") local logstr = string.format("%d\t%s\ttest_system", someone_id, someone_name ) syslog.syslog("LOG_INFO", logstr) syslog.closelog() |
rsyslog.confでは、テンプレート設定とルールを設定します。 この例の場合、時間ごとにファイルを切り替え、出力時間を先頭に付加した上で、プログラムから受け取った文字列を展開しています。
1 2 3 4 5 |
$template test_system,"/var/log/test_logs/test_system_log-%$year%%$month%%$day%%$HOUR%.log" $template test_system_format,"%timegenerated%%msg%\n" :syslogtag, contains, "test_system" -?test_system;test_system_format :syslogtag, contains, "test_system" ~ |
lua-cjson
http://www.kyne.com.au/~mark/software/lua-cjson.php
LuaからJSONを扱うモジュールです。C言語でコンパイルされているため非常に高速です。 アドサーバは直接データベースを参照するケースは稀で、memcached等のオンメモリデータを参照するケースが多いのですが、その際データをアドサーバに対して受け渡すのに手軽な方法がJSONです。弊社では他にもバイナリにするケースや、messagepackを用いるケースもありますが、手軽さと視認性の高さからJSONを使うことが最も多いです。JSONを採用する上で問題になるのがデコードにかかるコストなのですが、様々なモジュールや方法を試した結果、最も良好な速度だったのが、このlua-cjsonです。
サンプルコードは下記のような形になります。
1 2 3 4 5 6 7 8 9 10 |
local json = require "cjson" 中略 local flag, ad_data = pcall(json.decode, json_text) -- parse error if not flag then ngx.log(loglv, "[ERROR] iliegal json") ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) end |
まとめ
Luaは自分でC言語のモジュールを作ることが出来るので、Cのライブラリがあれば自分で高速なモジュールを作ることも可能です。弊社では、
- hiredisライブラリを利用したRedis操作モジュール
- libmemcachedを利用したmemcached操作モジュール
- opensslライブラリを利用した、暗号/複合化モジュール
などで利用しています。 C言語と連携しないと複雑な処理を高速に実行することが難しいのがLua言語の特徴ですが、今回ご紹介したような鉄板モジュールが開発チーム内で定まっていれば、C言語を扱えないプログラマでも手軽にLuaでアドサーバを書くことが可能になります。