Perlbal::Plugin::Regexcontrol
ロードバランサーにPoundを使う場合、
画像はこっちのサーバつかってね、
アプリはこっちのサーバつかってねって結構簡単にかけます。
こんな感じ。
UrlGroup "[^=]\.(jpg|gif|png|js|css|swf)$" HeadRequire Host "example.jp.*" BackEnd 192.168.200.1,80,1 BackEnd 192.168.200.2,80,1 EndGroup
こんな感じで特定の拡張子のアクセスの場合は
別のサーバに振り分けするとかできるのですが、
Perlbalの場合、デフォルトの機能でできませぬ。
と、悩んでいる時にmiyagawaさんからプラグインかけばできると
教えてもらったので書いてみた。
激しく微妙な感じですが。とりあえずうごいてるぽい。
package Perlbal::Plugin::Regexcontrol; use strict; use warnings; no warnings qw(deprecated); our %Services; # service_name => $svc # when "LOAD" directive loads us up sub load { my $class = shift; Perlbal::register_global_hook('manage_command.regex', sub { my $mc = shift->parse(qr/^regex\s+(?:(\w+)\s+)?(\S+)\s*=\s*(\w+)$/, "usage: REGEX [<regex>] <regex> = <dest_service>"); my ($selname, $regex, $target) = $mc->args; unless ($selname ||= $mc->{ctx}{last_created}) { return $mc->err("omitted service name not implied from context"); } my $ss = Perlbal->service($selname); return $mc->err("Service '$selname' is not a selector service") unless $ss && $ss->{role} eq "selector"; $ss->{extra_config}->{_regexs} ||= {}; $ss->{extra_config}->{_regexs}{$regex} = $target; return $mc->ok; }); return 1; } # unload our global commands, clear our service object sub unload { my $class = shift; Perlbal::unregister_global_hook('manage_command.regex'); unregister($class, $_) foreach (values %Services); return 1; } # called when we're being added to a service sub register { my ($class, $svc) = @_; unless ($svc && $svc->{role} eq "selector") { die "You can't load the regex plugin on a service not of role selector.\n"; } $svc->selector(\®ex_selector); $svc->{extra_config}->{_regexs} = {}; $Services{"$svc"} = $svc; return 1; } # called when we're no longer active on a service sub unregister { my ($class, $svc) = @_; $svc->selector(undef); delete $Services{"$svc"}; return 1; } # call back from Service via ClientHTTPBase's event_read calling service->select_new_service(Perlbal::ClientHTTPBase) sub regex_selector { my Perlbal::ClientHTTPBase $cb = shift; my $req = $cb->{req_headers}; return $cb->_simple_response(404, "Not Found (no reqheaders)") unless $req; my $uri = $req->request_uri; my $maps = $cb->{service}{extra_config}{_regexs} ||= {}; my ($regex, $val) = each %{$maps}; my $svc = Perlbal->service($val); if ($regex eq '*') { $svc->adopt_base_client($cb); return 1; } if ( $uri =~ /$regex/ ) { $svc->adopt_base_client($cb); return 1; } else { return 0; } } 1;
ただ、Vhostsプラグインと同時に使えるか分からない。ってか現状使えない。
selectorを多段でかませれば問題ないと思うんだけど、どうも動かない。
もし無理ならVhostsプラグインにパッチあてるしかないかもー。><
(追記)
ちょっとした設定例
CREATE SERVICE reg SET reg.role = selector SET reg.plugins = regexcontrol SET reg.persist_client = on REGEX reg \\.(txt)\$ = ws ENABLE reg CREATE SERVICE ws SET ws.role = web_server SET ws.docroot = $dir SET ws.dirindexing = 0 SET ws.persist_client = 1 SET ws.enable_put = 1 SET ws.enable_delete = 1 ENABLE ws