Lighttpd+mod_cmlを考えてみました

ダイナミックコンテンツをうまく利用するためのモジュールとしてmod_cmlというものがあります。mongrelで紹介されていたのが気になって調べてみることにしました。

一口にキャッシュといってもその有り様はアプリケーションにより千差万別、様々な場面が想定されるわけLighty+mod_cmlではその多様性を組込型言語luaを使ってプログラミングします。

Lighttpdのmod_cmlを使用するにはまず、lualibmemcacheをインストールして--memchacheと--luaオプションを付加してLightyをリメイクします。

tar zxvf lua-5.1.1.tar.gz 
cd lua-5.1.1
make linux
make linux install
tar jxvf libmemcache-1.4.0.rc2.tar.bz2
cd libmemcache-1.4.0.rc2
./configure
make
make install
export LUA_CFLAGS='-I/usr/local/include'
export LUA_LIBS=/usr/local/lib/liblua.a
./configure --with-memcache --with-lua
chcon -c -v -R -u system_u -r object_r -t textrel_shlib_t \
 /usr/local/lib/mod_cml.so

これで、準備完了(chcon ~ ... はSELinuxの設定)。lighttpdのコンフィグレーションはたった一行。これですべてのリクエストの前にpower-magnet.cmlが実行されます。

cml.power-magnet  = "/path/to/rubricks/config/power-magnet.cml"

この、power-magnet.cmlにluaでアプリケーション固有のキャッシュ処理を記述します。Railsにはそもそもキャッシュ機能がありますのでアプリケーション側では特別な処理は必要ありません。後は、power-magnet.cmlにコードを記述するわけですがluaを使ってプログラミングするといってもゼロから書き始めるわけではなく、mod_cmlにはすでにいくつかの変数・関数が定義されていますのでこれを使用します。

  • request["REQUEST_URI"]
  • request["SCRIPT_NAME"]
  • request["SCRIPT_FILENAME"]
  • request["DOCUMENT_ROOT"]
  • request["PATH_INFO"]
  • request["CWD"]
  • request["BASEURI"]
  • get["パラメータ名"]
  • string md5(string)
  • number file_mtime(string)
  • number file_isreg(string)
  • number file_isdir(string)
  • number dir_files(string)
  • string memcache_get_string(string)
  • number memcache_get_long(string)
  • boolean memcache_exists(string)

変数も関数も名前でなんとか意味はわかります。file_isreg()だけはわからなかったのですがソースをみたらstat(...) S_ISREG(st.st_mode)でしたの単にレギュラーファイルか否かをチェックしているだけです。「..」は文字連結連結。

これらを踏まえてMongrel: Lighttpdの例をみると最初のブロックでは、いわゆる「ただいまメンテナンス中です...」のファイルがあったら即それを表示。以降の処理でURIをチェックしてファイル名を作成し、そのファイルがfile_isregであれば、output_includeにそのファイル名を挿入します。mod_cmlでは戻り値が0(CACHE_HIT)であればoutput_includeからファイルを読み込みそれを出力する仕掛けです。コンテントタイプを指定する場合はoutput_contenttype="text/html"のように設定します。

dr = request["DOCUMENT_ROOT"]
if file_isreg(dr .. "/maintainance.html") then
  output_include = { dr .. "/maintainance.html" }
  return CACHE_HIT
end
f = request["REQUEST_URI"]
if f  "/" or f  "" then
  file = dr .. "index.html" 
elseif not string.find(f, "%.") then
  file = dr .. f .. ".html" 
else
  file = dr .. f
end
if file_isreg(file) then
  output_include = { file }
  return CACHE_HIT
end
return CACHE_MISS

ここまで調べてみて、んんん~mod_rewriteや条件構文でもいいんじゃないかなっていう気がしてきました。まあ、お勉強したということで。

この記事のトラックバックURL:

http://hippos-lab.com/blog/trackback/89

返信