mod_accessvalve
lighttpd で一定時間におけるアクセス数をもとにアクセスを制限したいという用件があったのですが、それにマッチする良いモジュールがなかったので試しに書いてみた。
設定項目は
accessvalve.bucket-size
:reset-interval
の時間内に許可するリクエスト数accessvalve.reset-interval
: リクエスト数カウントをリセットする時間(秒) (デフォルト 60)accessvalve.ban-duration
: リクエスト数がbucket-size
を超えた場合にアクセスを拒否する時間(秒)(デフォルト 900)
という感じで。また bucket-size
を指定しない、もしくは 0
に設定するとそのブロックではこの機能は無効になる。
このようなアクセス制限をあえて HTTPD でやる利点としては、Virtual Hostごとに設定を変えたり、特定のパスだけ制限したりと言うことができると言うことかなぁ。あとは 503 エラーとかかえせたりとかか。その分無駄なループが発生するのでオーバーヘッドになる。
最初 lighttpd のサイトを検索すると mod_throttle
というのを誰かが書いているのが見つかってそれを使おうとしたのだけど、設定ファイルの patch 処理がされてなく、上記のような設定ファイルの場所によって設定を変えるということができなかったので採用を見送った。
また、単純なコネクションごとの帯域制限やコネクション数制限は lighttpd に付属の mod_evasive でできる。
なぜか X 関係でビルドできないとき
lighttpd 1.4.24 以降や現在の SVN head で autogen.sh
を走らせてからビルドしようとするとなぜか X 関係のエラーが出て make
が失敗するということがありますがそういうときは、
cp `which libtool` .
とかすると make
とおるようになります。それ以上追ってないけど。なんでだろ?
lighttpd だけで多言語サイトを作る方法
lighttpd 1.4.21 以上では $HTTP["language"]
という新しい変数(?)が設定の中で使えるようになり、これを使用するとクライアントの Accept-Language
に応じて lighttpd の設定を変えることが可能になります。
これを利用して多言語化しているサイトとしては opensource.kayac.com が有名です。
このサイトは以下のような設定で動作しております。
$HTTP["url"] !~ "^/(?:(?:css|js|img|images?|static|tmp)/|[^/]+\.[^/]+$)" {
$HTTP["url"] !~ "^/(en|ja)(?:$|/)" {
$HTTP["language"] =~ "(en|ja)" {
url.redirect = ( "^/(.*)" => "/%1/$1" )
}
$HTTP["language"] !~ "(en|ja)" {
url.redirect = ( "^/(.*)" => "/en/$1" )
}
}
}
ちょっとややこしいですが、
$HTTP["url"] !~ "^/(?:(?:css|js|img|images?|static|tmp)/|[^/]+\.[^/]+$)" {
で、cssやjsディレクトリ、もしくはルート直下のファイルへのアクセスはそのまま。
$HTTP["url"] !~ "^/(en|ja)(?:$|/)" {
で、すでに /ja/
や /en/
へのリクエストであればそのまま。
上記に該当しなかった場合、
$HTTP["language"] =~ "(en|ja)" {
url.redirect = ( "^/(.*)" => "/%1/$1" )
}
で、Accept-Context
が en か ja の場合はそれに応じてリダイレクト先を振り分ける。それ以外の時(対応していない言語の場合)は
$HTTP["language"] !~ "(en|ja)" {
url.redirect = ( "^/(.*)" => "/en/$1" )
}
で、デフォルトの言語(ここではen)にリダイレクトする。
というような感じで動作しております。
このような使い方以外にもさまざまな使い方ができそうですね。覚えておくともしかしたら使えるかもしれません。
CGI用の設定
こういうようなFastCGI用の設定のCGIバージョン。
こんな感じかなー。
server.document-root = "/Users/typester/dev/scratch/myapp/root"
$HTTP["url"] !~ "^/(css/|images?/|js/|static/|tmp/|[^/]+\.[^/]+$)" {
cgi.assign = ( "" => "" )
alias.url = (
"" => "/Users/typester/dev/scratch/myapp/script/myapp.cgi",
)
}
lighttpd 1.4.20 は CGI の STDERR をエラーログに出してくれない。
のでちょっとはまった。なんなんだ。
コードを見るとなぜか /dev/null
にリダイレクトしちゃっている。
ログを追うと、
http://redmine.lighttpd.net/repositories/revision/lighttpd/2163
この変更によるものらしいが、正直何してるのかよくわからない。
とりあえず STDERR が闇に葬られるとか不便すぎるので
diff --git a/src/mod_cgi.c b/src/mod_cgi.c
index 6f27f8b..18f88c2 100644
--- a/src/mod_cgi.c
+++ b/src/mod_cgi.c
@@ -987,8 +987,6 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *
*c = '/';
}
- openDevNull(STDERR_FILENO);
-
/* we don't need the client socket */
for (i = 3; i < 256; i++) {
if (i != srv->errorlog_fd) close(i);
などとしておいた。1.4.x 系では今のところ最新の 1.4.20 だけがこうなってる。
チケット作っとこうとしたらもうあった。
次のバージョンでは直ると良いね。
lighttpd+fastcgiで
fastcgiだけ再起動したい場合に、再起動中にアクセスあるとfastcgiプロセスが上がったあとも500になってしまうことがあるのだけど、みんなどうしてる?
学生さんのcatアプリ見せてもらった。なんかすごいがんばってた。
Chainedアクションがないころのなのか、/wiki/{pagename}/edit
とかそれ系のコントローラを Regex コントローラでがんばってたりしてた。
Plugin::Images
とかつかってた。しらんかった。なんかあれだなーと思ったら作者見て納得。nothingmuch のか。
Plugin::Static::Simple
とかは使わないほうがいいよ。静的ファイルはサーバー直でやんないと無駄。ロードするだけですらッ!
それで思い出したけど、lighttpdの設定、最近 mod_alias
も mod_setenv
も mod_rewrite
もつかわない書式を思いついて使ってる。
$HTTP["url"] =~ "^/(?!favicon\.ico$|static/|js/|css/|images?/)" {
fastcgi.server = (
"" => (
( "socket" => "/path/to/myapp.socket",
"check-local" => "disable", ),
),
)
}
こんなの。
とにかく、技術はどうあれ、作ってみる、形にするってことはやっぱり重要だなと思った。口だけなら何でもいえる。
C::P::XSendFile supported X-LIGHTTPD-send-tempfile
1.5 動いた記念。
http://svn.unknownplace.org/public/library/perl/trunk/Catalyst-Plugin-XSendFile/
Plugin::XSendFile をアップデート。あとでdevリリースでCPANに。
# myapp.yml
sendfile:
tempdir: /dev/shm
して
use Catalyst qw/XSendFile/;
するだけで、出力が 16kbyte 以上のときは自動で X-LIGHTTPD-send-tempfile 経由での出力になるって感じ。
16kbyte って閾値と、それ以前に勝手にsendfileるのは設定できるようにしたほうが良いな。ま、おいおい。
んで、確かに速いんだけど、なんか不安定。ベンチってたんだけど fastcgi プロセス反応なくなるときがある。
XSendFile の使用有無にかかわらずそうなのでfastcgiサポート自体の問題くさいけどよくわからない。
Catalyst on Lighttpd 1.5.0
新しいのでてたのでリベンジ。
server.modules = (
"mod_proxy_core",
"mod_proxy_backend_fastcgi",
)
server.document-root = "/home/typester/tmp/MyApp/root"
server.port = 3000
proxy-core.balancer = "round-robin"
proxy-core.protocol = "fastcgi"
proxy-core.backends = ( "unix:/home/typester/tmp/MyApp/fcgi.socket" )
でとりあえずMyApp動いた。
バックエンドがひとつの場合でも proxy-core.balancer を必ず指定しないといけないようだ。でないと
mod_proxy_core.c.1550: (trace) backlog: all backends are down, putting /foo (4) into the backlog
といわれてしまう。
この間はそれでできなかっただけかも!
X-Rewrite-* や X-LIGHTTPD-send-tempfile など楽しげな機能でやっと遊べる><
あと mod_uploadprogress
のソースもついてきていて、configureスクリプトの do_build のところに追加で書いてみたらビルドできた。これでも遊んでみたい。