モダンmod_perl入門 #yapcasia
Upcoming SlideShare
Loading in...5
×
 

モダンmod_perl入門 #yapcasia

on

  • 6,348 views

YAPC::Asia Tokyo 2012 の 2日目9月29日の夕方のトーク「モダンmod_perl入門」のスライドです。

YAPC::Asia Tokyo 2012 の 2日目9月29日の夕方のトーク「モダンmod_perl入門」のスライドです。

Statistics

Views

Total Views
6,348
Slideshare-icon Views on SlideShare
4,908
Embed Views
1,440

Actions

Likes
7
Downloads
16
Comments
0

5 Embeds 1,440

http://yapcasia.org 1427
http://webcache.googleusercontent.com 9
https://twitter.com 2
http://s.deeeki.com 1
http://www.google.com 1

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • 当然Apache1とApache2の歴史はそれより前\n2003年にはApache2/mod_perl2が出ていたけど、当時はまだこなれていなかったので、2003年のリモートメール第4世代はApache1.3/mod_perl1で作成しました\n
  • 書いたことがある方も多い、基本ですね\nスペースの都合で改行を \\ でエスケープしています。実際にこういう書き方もできます\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • ・workerすなわちスレッドというものもありますが、スレッドセーフなPerlプログラム(いや、Perlに限らず)は難しいので避けます\n
  • \n
  • \n
  • ・単に「フェーズ」とも言います\n
  • ・皆さんの興味のあるレスポンス処理をオレンジで塗っています\n・PerlHandler Apache::Registry とはコレ\n
  • ・処理フェーズを一巡したリクエストサイクルの図です\n・これはApache1の図なので、Perl*Handlerではなく役割名の英単語になっています\n・簡単に読み替えできます\n・各フェーズでエラーをreturnすると、そこでresponseをもげってloggingに行きます\n
  • ・PerlHandler → PerlResponseHandler\n・PerlResponseHandler ModPerl::Registry はこれです\n・PerlMapToStorageHandler は mod_perl1 の PerlTransHandler の仕事を分業するために出来た新しいフェーズ\n
  • ・フィルタについては割愛します\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • ・今回はPerlProcessConnectionHandlerにフォーカスを当てます\n・これらをひっくるめてConnectionフェーズと言ったりすることもあります\n
  • \n
  • \n
  • ・Apache2 Connection で動くし。Experimentalだって古い資料には書かれていたけど\n・AnyEventベースのものは最新のにも無いようですが、作ると面白いかもしれませんね\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

モダンmod_perl入門 #yapcasia モダンmod_perl入門 #yapcasia Presentation Transcript

  • モダンmod_perl入門 (Modern mod_perl Guide) 尾形 鉄次 (OGATA Tetsuji) Twitter: @xtetsuji 2012/09/29 YAPC::Asia Tokyo 2012
  • Attention for audience• This slide is mainly written by Japanese, and few English. In the future, I will write and share this slide of English version, perhaps.• I speach by Japanese language.• If you do not known Japanese language, please fun and feel from some Perl code and few English description on this slide.
  • Self-introduction
  • 自己紹介• 尾形 鉄次 (OGATA Tetsuji)• Twitter: @xtetsuji• Blog: http://post.tetsuji.jp/• SlideShare: http://www.slideshare.net/xtetsuji• よく行く: Hokkaido.pm, Hachioji.pm• 得意技: mod_perl (他はよく知らない)
  • 所属紹介• 株式会社fonfun(フォンファン) http://www.fonfun.co.jp/ • 主力製品:リモートメール http://rmail.jp/
  • Agenda
  • Agenda• About mod_perl basics• mod_perl handler basics• Refactoring mod_rewrite• mod_perl meets PHP• Apache worker MPM and Perl ithreads• compare mod_{lang} families• In future my activities
  • If time is left• Compare with others• Connection cycle: Let’s make SMTP Server by mod_perl• Other topics
  • In the first
  • Respect for ... モダンPerl入門(翔泳社 2009; http://books.shoeisha.co.jp/book/b73388.html )
  • 参考文献• 洋書になりますが、mod_perlを勉強する 上で役立つ3冊 • Practical mod_perl (Orelly 2003; http://modperlbook.org/) • The mod_perl Developer’s Cookbook (Sams Publishing 2002; http://www.modperlcookbook.org/) • mod_perl2 User’s Guide (Onyx Neon 2007; http://modperl2book.org/)
  • About mod_perl basics
  • History of mod_perl• mod_perl1 first public release: 1996/3/25 (see: http://perl.apache.org/dist/mod_perl-1.0-current/Changes)• mod_perl2 first public release: 2002/4/6 (see: http://perl.apache.org/dist/mod_perl-2.0-current/Changes)
  • Perl CGI の高速化• mod_perl1 # ↓Apache Configurations AddHandler perl-script .pl PerlHandler Apache::Registry• mod_perl2 AddHandler perl-script .pl PerlResponseHandler ModPerl::RegistryPrefork• こう書くことで、拡張子”.pl”のPerl CGI が高速化する (Registry→PerlRunでも可)
  • Perl CGIの高速化• CGI.pm、CGI::Simple 等は内部で mod_perl高速化環境をサポート済み• とはいえ永続環境なので、グローバル 変数の扱い等注意が必要 →モダンPerlなコードを書こう
  • mod_perlって何?• Perl CGIの高速化?→副次的な効果• 本当は「Apacheがモジュールで提供す る機能をC言語を使わずPerlで書ける ようにしたもの」がmod_perl• C言語が読み書きできない俺歓喜
  • About mod_perl basics• Perl CGIの高速化についてはだいぶ割愛 させていたきますが、世間に出回って いる間違った知識の是正だけはどこか でしたい• 後はApacheのmod_perl拡張ハンドラを 読み書きして楽しみましょう
  • mod_perl handler basics
  • mod_perl essence is extension of Apache• mod_perl の Perl CGI高速化環境では、 HTTPリクエストを受けてレスポンスを 返すことが出来るのは周知の通り• mod_perlはHTTPレスポンスを返すだけ でなく、その前処理や後処理もできる
  • Apache internal• MPMは多く使われているpreforkを想定• 親プロセスを起動すると、設定に従って 子プロセスを設定の数だけ起動(prefork)• 各子プロセスはHTTPリクエストを待つ• では子プロセスごとのHTTP処理は...
  • Apache internal• リクエストを受ける• ヘッダを解析する• 必要に応じてURLを変換したり、DocumentRootを手がかりに実パスを 割り出す• アクセス制御、認証、承認(BASIC認証など)• MIMEタイプを考える• レスポンスを出す(静的ファイル、プログラム出力)• ログ(アクセスログ、エラーログ)を出力する• 次のリクエストを待つ
  • Apache internal• 各処理を行っている部分にはフックが あって、ここに各種処理を挟むことが 可能 → Apache Module(mod_xxxxxx)• Apache Module でできることを Perl でできるようにしたもの → mod_perl
  • Apache/mod_perl process phase• 各フックがある部分: 「(処理)フェーズ」• リクエスト待ち状態から各フェーズを 一巡するので、全体を 「リクエストサイクル」と呼びます
  • Phase of mod_perl1 PerlChildInitHandler PerlPostReadRequestHandler PerlInitHandler PerlTransHandler PerlHeaderParserHandler PerlAccessHandler PerlAuthenHandler PerlAuthzHandler PerlTypeHandler PerlFixupHandler PerlFixupHandler PerlHandler PerlLogHandler PerlCleanupHandler PerlChildExitHandler ※一部省略があります。詳しくは以下を参照 http://perl.apache.org/docs/1.0/guide/config.html#toc_Perl_Handlers
  • Phase of mod_perl1 ※「Practical mod_perl」より抜粋
  • Phase of mod_perl2 PerlChildInitHandler PerlPostReadRequestHandler PerlInitHandler PerlTransHandler PerlMapToStorageHandler PerlHeaderParserHandler PerlAccessHandler PerlAuthenHandler PerlAuthzHandler PerlTypeHandler PerlFixupHandler PerlFixupHandler PerlResponseHandler PerlLogHandler PerlCleanupHandler PerlChildExitHandler ※かなり省略があります。詳しくは以下を参照 http://perl.apache.org/docs/2.0/user/config/config.html
  • Phase of mod_perl2 ※「Practical mod_perl」より抜粋
  • first mod_perl1 handler package MyApache::Hello; use strict; use warnings; use Apache::Constants qw(OK); sub handler { my $r = shift; # "Apache" object $r->send_http_header(text/plain); $r->print("Hello! mod_perl1.n"); return OK; } 1;
  • first mod_perl2 handlerpackage MyApache2::Hello;use strict;use warnings;use Apache2::RequestRec (); # for $r->content_type()use Apache2::RequestIO (); # for $r->print()use Apache2::Const -compile => qw(OK);sub handler { my $r = shift; # "Apache2::RequestRec" object $r->content_type(text/plain); $r->print("Hello! mod_perl2.n"); return Apache2::Const::OK;}1;
  • Apache{1,2} configs # Apache1 <Location /> SetHandler perl-script PerlHandler MyApache1::Hello </Location> # Apache2 <Location /> SetHandler modperl PerlResponseHandler MyApache2::Hello </Location>
  • first mod_perl handler• 全ては sub handler と $r の受け取りから • これはどの処理フェーズでも同様• mod_perl2 では $r のメソッド群が各種 別パッケージで管理されているため、 メソッドによって事前に適切な Apache2::* を use しておく必要がある
  • first mod_perl handler• PerlHandler / PerlResponseHandler にハン ドラをセットしておけば、全てのファ イルの処理をフックできるので、*.html ファイル等をあたかも透過的に処理す ることができる → 絵文字処理など
  • Refactoringmod_rewrite
  • About mod_rewrite• URLを書き換えるApacheモジュール• 「Apacheのスイス製アーミーナイフ」• 簡単なコードでURL書き換えが可能だ けれど、数十行も書けば魔窟の完成• 黒魔術と呼ばれる理由
  • Refactoring mod_rewrite• mod_perl では PerlTransHandler という URL を書き換えるフェーズを用意して いる• ここに URL 変換処理を挟める
  • Apache1 URI Transpackage MyApache1::Trans;use strict;use warnings;use Apache::Constants qw(DECLINED);sub handler { my $r = shift; my $uri = $r->uri(); # e.g. "/path/to/foo.html" ### ... modify $uri ... $r->uri($uri); return DECLINED; # I tell a lie that I do nothing.}1;
  • Apache2 URI Transpackage MyApache2::Trans;use strict;use warnings;use Apache2::RequestRec (); # for $r->uri()use Apache2::Const -compile => qw(DECLINED);sub handler { my $r = shift; my $uri = $r->uri(); # e.g. "/path/to/foo.html" ### ... modify $uri ... $r->uri($uri); # set $uri return Apache2::Const::DECLINED; # I tell a lie that I do nothing.}1;
  • Apache{1,2} configs # Apache1 # e.g. In <VirtualHost> Directive PerlTransHandler MyApache1::Trans # Apache2 # e.g. In <VirtualHost> Directive PerlTransHandler MyApache2::Trans
  • mod_perl URI Transpros than mod_rewrite• mod_rewriteに比べて可読性が高くなる• DBを引いたりmemcachedにアクセスし たりPerlで出来ることは何でもできる
  • mod_perl URI Transcons than mod_rewrite• 複数のファイル管理が必要となる(*.pm)• Perl/mod_perlが分からない担当者への 引き継ぎが難しくなる• Directory Context(<Location>, .htaccess) に書かれたmod_rewrite設定の場合は、 別途ケアが必要なケースもある
  • mod_perl meets PHP
  • PHP pathetic story of Perl Monger• 誰かが発注したアプリがPHP製で、既に 勝手に納品しちゃっている• 蓋を開けると実装とかがテキトウ過ぎ• 契約や諸々の理由で手を入れられない• 運用担当でPerlしか知らない俺がPHPの デバッグとか…
  • mod_perl meets PHP• PHPが実行される前後にmod_perlで何か フックを差し込めないか • PHP処理前に認証・許可処理 • PHP処理後に出力をフィルタ…等々
  • Review request phase
  • Access/Authen/Authz and PHP• session_*()の使い方等がダメなケースで は、PHP中のそれらのコードを除去して mod_perlのAccess/Authen/Authzフェーズ で対処するケースも考えられる• Cookie、X-UP-Subno等のRequest Header は全て読める → 認証を肩代わりできる
  • package MyApache2::Auth;use strict;use warnings;# $r->headers_in() and $r->headers_out() returns APR::Tableuse APR::Table ();use Apache2::RequestRec ();use Apache2::Const -compile => qw(OK REDIRECT);sub handler { my $r = shift; my $cookie = $r->headers_in->get(Cookie); # raw cookie my $x_up_subno = $r->headers_in->get(X-UP-Subno); my ($is_success, $location, $set_cookie); ### ### ... modify and analyze this session information ... ### if ( $is_success ) { $r->headers_out->set(Set-Cookie => $set_cookie); return Apache2::Const::OK; } else { $r->headers_out->set(Location => $location); $r->err_headers_out->set(Location => $location); return Apache2::Const::REDIRECT; }} # e.g. In <VirtualHost> Directive1; PerlAccessHandler MyApache2::Auth
  • Request output filter and PHP• PHPの出力をフィルタする• Apache2のネイティブフィルタなので、 PHPの ob_*() (output buffering) 等の設定 に一切影響されない• 応用例: 絵文字変換、PHPで書ききれな い部分を後で置換する、等々
  • Requets output filter practice• Filter の場合 sub handler { ... } は $r (Request Object)ではなく、 $f (Filter Object) を第一引数に受け取る• PerlOutputFilterHandler ディレクティブ• 今回は改行を除去する簡単なサンプル を紹介
  • package MyApache2::FilterObfuscate;use APR::Table ();use Apache2::Filter ();use Apache2::RequestRec ();use Apache2::Const -compile => qw(OK);my $READ_CHUNK_LENGTH = 2048;sub handler { my $f = shift; # $f is "Apache2::Filter" object ### If filter is chained, this filter is first? unless ($f->ctx) { $f->r->headers_out->unset(Content-Length); $f->ctx(1); } while ($f->read(my $buffer, $READ_CHUNK_LENGTH)) { $buffer =~ s/[rn]//g; $f->print($buffer); } return Apache2::Const::OK;}1; # e.g. In <VirtualHost> Directive <FilesMatch “.*(html?|php)$”> PerlOutputFilterHandler MyApache2::FilterObfuscate </FilesMatch>
  • PHP and Perl are friend• Apacheの上でPHPとPerlは友達!• 他にも各種フックを使ってmod_perlは PHPを助けることができる• 可能性は無限大
  • Apache worker MPM and Perl ithreads
  • Apache worker MPM and Perl ithreads• Apache worker MPM: スレッド(pthread) とプロセスのハイブリット動作• Perl ithreds: 嫌われ者 • 同時並行処理するならParallel::Prefork 等やAnyEventを使うのが今のPerl流儀
  • スレッドのメリット• 各リクエストフェーズ間で変数共有が 可能 (poor man’s memcached?)• 何か人とは違う事をしてるワクワク感
  • スレッドのデメリット• Perl ithreadsが安定していない• 各スレッド毎にインタープリタプール を作成する設計上、preforkとコストは それほど変わらない• スレッドセーフを意識する必要がある
  • Instruction worker MPM & mod_perl• worker MPM上でのmod_perlのノウハウ は特に少ないのでハマると危険• Perlのスレッドは不安定である事を心得 た上で、複雑な事はさせてはいけない
  • Queue server by mod_perl2 thread• 今回はスレッドの変数共有を利用した mod_perl2の文字列Queueサーバを実演• “POST /” でRequest BodyをQueueing、• “GET /” でQueueをPickup
  • Queue server by mod_perl2 thread (1)package My::Queue;use strict;use warnings;use threads;use threads::shared;my @queue :shared;sub push_queue { my $value = shift; return 0 if !defined $value; push @queue, $value; return 1;}sub shift_queue { return shift @queue}1;
  • Queue server by mod_perl2 thread (2)package MyApache2::ThreadQueue;use strict;use warnings;use threads;use Apache2::RequestRec ();use Apache2::RequestIO ();use Apache2::Const -compile => qw(OK HTTP_METHOD_NOT_ALLOWED);use My::Queue;my $READ_CHUNK_LENGH = 2048;###### ... following sub handler { ... } ...###
  • Queue server by mod_perl2 thread (3)### continuedsub handler { my $r = shift; if ( $r->method eq POST ) { my $value; while ( $r->read(my $buf, $READ_CHUNK_LENGH) ) { $value .= $buf; } My::Queue::push_queue($value); $r->content_type(text/plain); $r->print(Queued); return Apache2::Const::OK; } elsif ( $r->method eq GET ) { my $retval = My::Queue::shift_queue(); $r->content_type(text/plain); $r->print($retval); return Apache2::Const::OK; } else { return Apache2::Const::HTTP_METHOD_NOT_ALLOWED; }}1;
  • worker MPM andperl ithreads practice• 複雑な事はさせてはいけない• 複雑な事をさせる場合には十分試験を• 大事なことなので(ry• 前出のQueue serverは100KB程度の文字 列の入出力を10K/minさせても問題無し
  • compare mod_{lang} families
  • mod_{lang} (1)• mod_perl: 最も歴史が古いものの一つ• mod_ruby: 開発停滞状態→mod_mruby• mod_python: 開発停滞状態• mod_lua: Apache2.4からコアモジュール• mod_mruby: 2012年4月に登場し活発
  • mod_{lang} (2)• mod_wsgi: Python WSGI 実装• mod_php: いわゆるPHP • こちらは今までの意味でApacheを 「拡張」するものではない• 他にもたくさんmod_{lang}はあるらしい
  • Benchmark http://blog.matsumoto-r.jp/?p=2669 より
  • Benchmark http://blog.matsumoto-r.jp/?p=2669 より
  • Benchmark• Perl CGI高速化環境(PerlRun, Registry)の 場合はmtime(ファイルの最終更新日時) を都度見るので、statシステムコールの コストが無視できない• mod_perlネイティブハンドラで勝負!
  • Benchmark• 実際、mod_perlネイティブハンドラで 同等のベンチマークを行うと About 7000 Response/secとのこと (Thanks @matsumotory)• Yet another perl5 implement で mod_*perl を作ると良い勝負ができるかな
  • In future my activities
  • In future my activities• mod_perlの役立つ情報やコードを公開 していきたい• mod_perlで困っている人を助けたい
  • In future my activities• 今後もmod_perl界隈を盛り上げたい• Twitterアカウント作った @mod_perl_info• ウェブサイトも作成中(未完成) http://modperl.info/• 詳細、割愛した部分の続きはどこかで
  • Timeup?
  • Questions?
  • ☆Service Slides☆
  • Compare with others
  • Compare with others• Pure CGI• FastCGI• PSGI/Plack, WAF
  • mod_perl and pure CGI• パフォーマンスを要求しなければ良い• Apache以外のウェブサーバでも使える• レンタルサーバ等、mod_perlすら使え ない環境は未だに多い
  • mod_perl and FastCGI• どちらも同じ永続環境、適材適所• Apache拡張ならmod_perl、CGIの高速化 のみならFastCGI• mod_perlの場合Apacheプロセス自身が 肥大化していくことを嫌う向きもある
  • mod_perl and PSGI/Plack, WAF• モダンなウェブアプリを今から書くの であればPlackベースのWAFを選ぼう• Apacheを拡張して他の言語との連携や Apache自体の動作を拡張できるのは mod_perlの面目躍如
  • Should you choice mod_perl?• Apacheという枠の中ではあるものの、 mod_perlの可能性はとても広い• パフォーマンス、移植性、様々な要素 を検討して、mod_perlを使うか考える• 既にあるApache上のレガシーコードを リファクタリングするなら良い選択
  • Connection cycle: Let’s make SMTPServer by mod_perl
  • Connection cycle• HTTP以外のサーバを書きたい• Apacheと同様の安定性が欲しい• Apache2/mod_perl2では、Connectionを HTTP以外の自前のものに書き換える事 ができる (e.g. mod_ssl)
  • AboutConnection Cycle PerlPreConnectionHandler PerlProcessConnectionHandler ※「Practical mod_perl」より抜粋
  • Why I want to write SMTP server by perl• DB引きたい• 絵文字処理したい• 通常のMTA(Sendmail/qmail/Postfix等)の pipeではスケールできない
  • Qpsmtpd• http://smtpd.develooper.com/• 実際に私(会社)もmod_perl2 Connection cycleでSMTPサーバを実装してみたもの の、既にPerl界隈にはQpsmtpdという MTAがある
  • Qpsmtpd has some Engine=Transport• pipe (CGI like)• fork-server• prefork-server• Apache (Apache::Qpsmtpd)• async (Danga::Socket base)
  • Qpsmtpd’s Apache::Qpsmtpd• Apache2 / mod_perl2 の Connection cycle の良い応用例• これを見るとApache2をEngineとして MTAを作る方法が良く分かる
  • Other topics
  • Test of mod_perl handler• 「モダンPerl入門」に詳しく書いてある• Apache2::FakeRequestを使って偽物の$r を作ってハンドラをテストできる• 処理単位のテストはTest::More等で• 詳しくは割愛、もしくは上述の書籍を
  • nginx: HttpPerlModulehttp://wiki.nginx.org/HttpPerlModule
  • nginx: HttpPerlModule• 構文や考え方がmod_perl1と酷似 →mod_perlの知識を流用可能• ただしイベント駆動サーバならではの 各種制限もあるので注意• 世間での応用例も少し出てきている• 以前はEmbeddedPerlModuleという 名前だった(1.0→1.2で名称変更?)
  • nginx:HttpPerlModulepackage hello;use nginx;sub handler { my $r = shift; $r->send_http_header("text/html"); return OK if $r->header_only; $r->print("hello!n<br/>"); $r->rflush; if (-f $r->filename or -d _) { $r->print($r->uri, " exists!n"); } return OK;}1;__END__ http://wiki.nginx.org/HttpPerlModule より
  • nginx: HttpPerlModule• mod_perl2ではなくmod_perl1の構文の 影響を強く受けている ($r->send_http_headers()等に見られる)• nginx設定ファイルの書き方については 割愛→前述のWikiに詳細がある
  • 割愛したこと• Perl CGIの高速化環境の詳細• Apache2.4環境でのmod_perl→現時点 (2012/09)で正式にサポートしていない• Apache2.4 event MPM環境での mod_perl→上記同様
  • これからのApache• Apache2.4でmod_perlがサポートされた ら、event MPM上でmod_perl動かしたい• Apacheはこれからも進化していきます• mod_lua, mod_sedがApache2.4でコアモ ジュール入り、しかしExperimental扱い
  • Questions?
  • ご清聴ありがとうございました