YAPC::Asia 2012行ってきた
■[Perl] 平均レスポンスタイム50msをPerlで捌く中規模サービスの実装/運用
基本的にはWeb+DB Press Vol70に書いているものの補足
IOをとにかく減らす
Profile
* upstream response time
Test/CI
サーバ
■[Perl] Plack::Middleware::InteractiveDebuggerがすごい
plackup -e 'enable "InteractiveDebugger"' -a app.psgi で使える。
stacktraceを差し替えるモジュールなんだけど、stacktrace中で変数のdumpとかできる
StackTrace (most recent call first)
File "local/lib/perl5/Plack/Middleware/InteractiveDebugger.pm", line 108, in Plack::Middleware::InteractiveDebugger::__ANON__
$self->app->($env);
[console ready]
perl> use Data::Dumper
perl> Dumper $env
$VAR1 = {
'psgi.multiprocess' => '',
'SCRIPT_NAME' => '',
'SERVER_NAME' => 0,
'HTTP_ACCEPT_ENCODING' => 'gzip,deflate,sdch',
'HTTP_CONNECTION' => 'keep-alive',
'PATH_INFO' => '/die',
-- snip --
minicpanを工夫してみた
■[perl]minicpanを工夫してみた
外出時にcpanモジュール入れるのにminicpanを使っていますが、いちいちminicpanを起動して、オプション指定して、使い終わったら落とすという流れがめんどくさかったので、一連の流れをコマンドにしてみた。
(minicpan用のhttpdを常時起動しておいて、PERL_CPANM_OPTを指定しておけばいいだけですけど)
minicpanの保存先を予め決めておいて
minicpan -l ~/perl5/minicpan -r http://mirror/
こんな感じでcpanm_minicpanとして作成した。
#!/usr/bin/env perl use strict; use warnings; use Plack::Builder; use Plack::Middleware::Static; use Plack::Runner; use Test::TCP; my $server = Test::TCP->new ( code => sub { my $port = shift; my $app = builder { enable "Plack::Middleware::Static", path => qr{^/}, root => $ENV{HOME} . '/perl5/minicpan'; }; my @args = ("--port=$port"); unless ( $ENV{DEBUG} ) { push @args, '--access-log=/dev/null'; open STDERR, '>', '/dev/null' or die $!; open STDOUT, '>', '/dev/null' or die $!; } my $runner = Plack::Runner->new; $runner->parse_options(@args); $runner->run($app); }, ); printf STDERR "Start minicpan server: 0.0.0.0:%s (pid: %d)\n\n", $server->port, $server->pid; my $port = $server->port; system 'cpanm', '--mirror-only', "--mirror=http://localhost:$port/", @ARGV; printf STDERR "\nStopping minicpan server: 0.0.0.0:%s (pid: %d)", $server->port, $server->pid; undef $server;
zsh functionの_cpanmの補完対象に追加しておけば、補完も効く。
■[Perl] perlbrewのproxy対応
perlbrew (http://search.cpan.org/~gugod/App-perlbrew/)を教えてもらって便利そうなので使ってみたけど、proxy対応していなかったので、環境変数から呼ぶようにしてみました。
これで環境変数にhttp_proxyがあればproxy使ってくれます。
もう少し真面目に書いてCPANにパッチ送ろうかな。。。
注意点としては、HTTP::Liteのproxyメソッドが、http://host:port/ のフォーマットを前提にしているので、最後にスラッシュがないとうまく動きません。(昔yumもそんなんだったな。。。)
$ diff -ub perlbrew.orig perlbrew
--- perlbrew.orig 2010-05-31 18:36:45.630114803 +0900 +++ perlbrew 2010-05-31 18:40:10.086114474 +0900 @@ -922,6 +922,7 @@ my $http_get = sub { my ($url, $cb) = @_; my $ua = HTTP::Lite->new; + $ua->proxy if exists $ENV{http_proxy}; my $loc = $url; my $status = $ua->request($loc) or die "Fail to get $loc";
■[Perl] WWW::Mechanize + Proxy 認証
某サイトからデータ引っ張ってくるためにWWW::MechanizeとWeb::Scraperでコーディングした。
Mech + Proxy認証でハマったところ。。。
clone
my $mech_clone = $mech->clone
上記でcloneを作成すると、Proxyの設定はしてくれない。
そのため、元々のオブジェクトにおいてproxyメソッドでproxyを設定した場合は、プロキシを利用しない。
また、環境変数を設定しておきnewでenv_proxyを呼ばせて自動設定させた場合は、proxy認証部分(http://foo:bar@proxyhost:proxyportのfoo:bar部分)にアクセスしようとする。
実際の動作としては、$mech->{handlers}->{request_preprepare}にLWP::UserAgent::Proxyオブジェクトが入らない。
これは、$mech->cloneではLWP::UserAgentのcloneメソッドを利用している(下記参照)のでLWPのバグor仕様っぽい。
use base 'LWP::UserAgent'; --snip-- sub clone { my $self = shift; my $clone = $self->SUPER::clone(); $clone->cookie_jar( $self->cookie_jar ); return $clone; }
cloneするのにいちいちproxyを設定しなおすのも嫌なのでmechがproxyを持っていたら再度設定するように書き直した。
こんな感じ。
sub mech_fixup { package WWW::Mechanize; no warnings 'redefine'; *clone = sub { my $self = shift; my $clone = $self->SUPER::clone(); $clone->cookie_jar( $self->cookie_jar ); if(exists $self->{proxy}){ while(my ($k, $v) = each %{$self->{proxy}}){ $clone->proxy([$k],$v); } } return $clone; } }
Web::Scraperのドキュメント
Podが充実してないので若干使いにくい。
ぐぐれば山ほど出てくるし、ソース読めばいいとはいえPod充実させてほしいなぁ
デス
■[Perl]open関数とUTF8フラグとRedHatLinux9と
Perlのバージョンが5.8.0で、RedHatLinuxのデフォルトのlocaleがen_US.UTF-8になってるとopen関数で開いたファイルに自動的にUTF8フラグをつけようとするという罠があることがわかった。
ま、3引数のopen関数を使うか、Encodeモジュールをきちんと使うか、Localeをきちんと設定しておけば起きないんですが。
教訓としては、
ということで。。。
再現用プログラム
hoge.pl---
#!/usr/bin/perl -w
use strict;
use warnings;
use Jcode;
open(F,'hoge.txt');
my @line = <F>;
close F;
print Jcode->new(@line,'euc')->jis;
--------------
hoge.txt---
ほげ
--------------
hoge.txt : 文字コード EUC-JP
改行コード LF
再現可能な環境
- Perl version : 5.8.0
- Jcode : 0.83
- OS : Red Hat Linux 9
OSの文字コードの設定
/etc/sysconfig/i18n
---------------------------------
LANG="en_US.UTF-8"
SUPPORTED="en_US.UTF-8:en_US:en"
SYSFONT="latarcyrheb-sun16"
---------------------------------