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

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

モダンmod_perl入門 #yapcasia

6,958
views

Published on

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

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

Published in: Technology

0 Comments
7 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
6,958
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
19
Comments
0
Likes
7
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • \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
  • Transcript

    • 1. モダンmod_perl入門 (Modern mod_perl Guide) 尾形 鉄次 (OGATA Tetsuji) Twitter: @xtetsuji 2012/09/29 YAPC::Asia Tokyo 2012
    • 2. 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.
    • 3. Self-introduction
    • 4. 自己紹介• 尾形 鉄次 (OGATA Tetsuji)• Twitter: @xtetsuji• Blog: http://post.tetsuji.jp/• SlideShare: http://www.slideshare.net/xtetsuji• よく行く: Hokkaido.pm, Hachioji.pm• 得意技: mod_perl (他はよく知らない)
    • 5. 所属紹介• 株式会社fonfun(フォンファン) http://www.fonfun.co.jp/ • 主力製品:リモートメール http://rmail.jp/
    • 6. Agenda
    • 7. 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
    • 8. If time is left• Compare with others• Connection cycle: Let’s make SMTP Server by mod_perl• Other topics
    • 9. In the first
    • 10. Respect for ... モダンPerl入門(翔泳社 2009; http://books.shoeisha.co.jp/book/b73388.html )
    • 11. 参考文献• 洋書になりますが、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/)
    • 12. About mod_perl basics
    • 13. 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)
    • 14. 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でも可)
    • 15. Perl CGIの高速化• CGI.pm、CGI::Simple 等は内部で mod_perl高速化環境をサポート済み• とはいえ永続環境なので、グローバル 変数の扱い等注意が必要 →モダンPerlなコードを書こう
    • 16. mod_perlって何?• Perl CGIの高速化?→副次的な効果• 本当は「Apacheがモジュールで提供す る機能をC言語を使わずPerlで書ける ようにしたもの」がmod_perl• C言語が読み書きできない俺歓喜
    • 17. About mod_perl basics• Perl CGIの高速化についてはだいぶ割愛 させていたきますが、世間に出回って いる間違った知識の是正だけはどこか でしたい• 後はApacheのmod_perl拡張ハンドラを 読み書きして楽しみましょう
    • 18. mod_perl handler basics
    • 19. mod_perl essence is extension of Apache• mod_perl の Perl CGI高速化環境では、 HTTPリクエストを受けてレスポンスを 返すことが出来るのは周知の通り• mod_perlはHTTPレスポンスを返すだけ でなく、その前処理や後処理もできる
    • 20. Apache internal• MPMは多く使われているpreforkを想定• 親プロセスを起動すると、設定に従って 子プロセスを設定の数だけ起動(prefork)• 各子プロセスはHTTPリクエストを待つ• では子プロセスごとのHTTP処理は...
    • 21. Apache internal• リクエストを受ける• ヘッダを解析する• 必要に応じてURLを変換したり、DocumentRootを手がかりに実パスを 割り出す• アクセス制御、認証、承認(BASIC認証など)• MIMEタイプを考える• レスポンスを出す(静的ファイル、プログラム出力)• ログ(アクセスログ、エラーログ)を出力する• 次のリクエストを待つ
    • 22. Apache internal• 各処理を行っている部分にはフックが あって、ここに各種処理を挟むことが 可能 → Apache Module(mod_xxxxxx)• Apache Module でできることを Perl でできるようにしたもの → mod_perl
    • 23. Apache/mod_perl process phase• 各フックがある部分: 「(処理)フェーズ」• リクエスト待ち状態から各フェーズを 一巡するので、全体を 「リクエストサイクル」と呼びます
    • 24. 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
    • 25. Phase of mod_perl1 ※「Practical mod_perl」より抜粋
    • 26. 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
    • 27. Phase of mod_perl2 ※「Practical mod_perl」より抜粋
    • 28. 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;
    • 29. 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;
    • 30. Apache{1,2} configs # Apache1 <Location /> SetHandler perl-script PerlHandler MyApache1::Hello </Location> # Apache2 <Location /> SetHandler modperl PerlResponseHandler MyApache2::Hello </Location>
    • 31. first mod_perl handler• 全ては sub handler と $r の受け取りから • これはどの処理フェーズでも同様• mod_perl2 では $r のメソッド群が各種 別パッケージで管理されているため、 メソッドによって事前に適切な Apache2::* を use しておく必要がある
    • 32. first mod_perl handler• PerlHandler / PerlResponseHandler にハン ドラをセットしておけば、全てのファ イルの処理をフックできるので、*.html ファイル等をあたかも透過的に処理す ることができる → 絵文字処理など
    • 33. Refactoringmod_rewrite
    • 34. About mod_rewrite• URLを書き換えるApacheモジュール• 「Apacheのスイス製アーミーナイフ」• 簡単なコードでURL書き換えが可能だ けれど、数十行も書けば魔窟の完成• 黒魔術と呼ばれる理由
    • 35. Refactoring mod_rewrite• mod_perl では PerlTransHandler という URL を書き換えるフェーズを用意して いる• ここに URL 変換処理を挟める
    • 36. 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;
    • 37. 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;
    • 38. Apache{1,2} configs # Apache1 # e.g. In <VirtualHost> Directive PerlTransHandler MyApache1::Trans # Apache2 # e.g. In <VirtualHost> Directive PerlTransHandler MyApache2::Trans
    • 39. mod_perl URI Transpros than mod_rewrite• mod_rewriteに比べて可読性が高くなる• DBを引いたりmemcachedにアクセスし たりPerlで出来ることは何でもできる
    • 40. mod_perl URI Transcons than mod_rewrite• 複数のファイル管理が必要となる(*.pm)• Perl/mod_perlが分からない担当者への 引き継ぎが難しくなる• Directory Context(<Location>, .htaccess) に書かれたmod_rewrite設定の場合は、 別途ケアが必要なケースもある
    • 41. mod_perl meets PHP
    • 42. PHP pathetic story of Perl Monger• 誰かが発注したアプリがPHP製で、既に 勝手に納品しちゃっている• 蓋を開けると実装とかがテキトウ過ぎ• 契約や諸々の理由で手を入れられない• 運用担当でPerlしか知らない俺がPHPの デバッグとか…
    • 43. mod_perl meets PHP• PHPが実行される前後にmod_perlで何か フックを差し込めないか • PHP処理前に認証・許可処理 • PHP処理後に出力をフィルタ…等々
    • 44. Review request phase
    • 45. Access/Authen/Authz and PHP• session_*()の使い方等がダメなケースで は、PHP中のそれらのコードを除去して mod_perlのAccess/Authen/Authzフェーズ で対処するケースも考えられる• Cookie、X-UP-Subno等のRequest Header は全て読める → 認証を肩代わりできる
    • 46. 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
    • 47. Request output filter and PHP• PHPの出力をフィルタする• Apache2のネイティブフィルタなので、 PHPの ob_*() (output buffering) 等の設定 に一切影響されない• 応用例: 絵文字変換、PHPで書ききれな い部分を後で置換する、等々
    • 48. Requets output filter practice• Filter の場合 sub handler { ... } は $r (Request Object)ではなく、 $f (Filter Object) を第一引数に受け取る• PerlOutputFilterHandler ディレクティブ• 今回は改行を除去する簡単なサンプル を紹介
    • 49. 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>
    • 50. PHP and Perl are friend• Apacheの上でPHPとPerlは友達!• 他にも各種フックを使ってmod_perlは PHPを助けることができる• 可能性は無限大
    • 51. Apache worker MPM and Perl ithreads
    • 52. Apache worker MPM and Perl ithreads• Apache worker MPM: スレッド(pthread) とプロセスのハイブリット動作• Perl ithreds: 嫌われ者 • 同時並行処理するならParallel::Prefork 等やAnyEventを使うのが今のPerl流儀
    • 53. スレッドのメリット• 各リクエストフェーズ間で変数共有が 可能 (poor man’s memcached?)• 何か人とは違う事をしてるワクワク感
    • 54. スレッドのデメリット• Perl ithreadsが安定していない• 各スレッド毎にインタープリタプール を作成する設計上、preforkとコストは それほど変わらない• スレッドセーフを意識する必要がある
    • 55. Instruction worker MPM & mod_perl• worker MPM上でのmod_perlのノウハウ は特に少ないのでハマると危険• Perlのスレッドは不安定である事を心得 た上で、複雑な事はさせてはいけない
    • 56. Queue server by mod_perl2 thread• 今回はスレッドの変数共有を利用した mod_perl2の文字列Queueサーバを実演• “POST /” でRequest BodyをQueueing、• “GET /” でQueueをPickup
    • 57. 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;
    • 58. 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 { ... } ...###
    • 59. 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;
    • 60. worker MPM andperl ithreads practice• 複雑な事はさせてはいけない• 複雑な事をさせる場合には十分試験を• 大事なことなので(ry• 前出のQueue serverは100KB程度の文字 列の入出力を10K/minさせても問題無し
    • 61. compare mod_{lang} families
    • 62. mod_{lang} (1)• mod_perl: 最も歴史が古いものの一つ• mod_ruby: 開発停滞状態→mod_mruby• mod_python: 開発停滞状態• mod_lua: Apache2.4からコアモジュール• mod_mruby: 2012年4月に登場し活発
    • 63. mod_{lang} (2)• mod_wsgi: Python WSGI 実装• mod_php: いわゆるPHP • こちらは今までの意味でApacheを 「拡張」するものではない• 他にもたくさんmod_{lang}はあるらしい
    • 64. Benchmark http://blog.matsumoto-r.jp/?p=2669 より
    • 65. Benchmark http://blog.matsumoto-r.jp/?p=2669 より
    • 66. Benchmark• Perl CGI高速化環境(PerlRun, Registry)の 場合はmtime(ファイルの最終更新日時) を都度見るので、statシステムコールの コストが無視できない• mod_perlネイティブハンドラで勝負!
    • 67. Benchmark• 実際、mod_perlネイティブハンドラで 同等のベンチマークを行うと About 7000 Response/secとのこと (Thanks @matsumotory)• Yet another perl5 implement で mod_*perl を作ると良い勝負ができるかな
    • 68. In future my activities
    • 69. In future my activities• mod_perlの役立つ情報やコードを公開 していきたい• mod_perlで困っている人を助けたい
    • 70. In future my activities• 今後もmod_perl界隈を盛り上げたい• Twitterアカウント作った @mod_perl_info• ウェブサイトも作成中(未完成) http://modperl.info/• 詳細、割愛した部分の続きはどこかで
    • 71. Timeup?
    • 72. Questions?
    • 73. ☆Service Slides☆
    • 74. Compare with others
    • 75. Compare with others• Pure CGI• FastCGI• PSGI/Plack, WAF
    • 76. mod_perl and pure CGI• パフォーマンスを要求しなければ良い• Apache以外のウェブサーバでも使える• レンタルサーバ等、mod_perlすら使え ない環境は未だに多い
    • 77. mod_perl and FastCGI• どちらも同じ永続環境、適材適所• Apache拡張ならmod_perl、CGIの高速化 のみならFastCGI• mod_perlの場合Apacheプロセス自身が 肥大化していくことを嫌う向きもある
    • 78. mod_perl and PSGI/Plack, WAF• モダンなウェブアプリを今から書くの であればPlackベースのWAFを選ぼう• Apacheを拡張して他の言語との連携や Apache自体の動作を拡張できるのは mod_perlの面目躍如
    • 79. Should you choice mod_perl?• Apacheという枠の中ではあるものの、 mod_perlの可能性はとても広い• パフォーマンス、移植性、様々な要素 を検討して、mod_perlを使うか考える• 既にあるApache上のレガシーコードを リファクタリングするなら良い選択
    • 80. Connection cycle: Let’s make SMTPServer by mod_perl
    • 81. Connection cycle• HTTP以外のサーバを書きたい• Apacheと同様の安定性が欲しい• Apache2/mod_perl2では、Connectionを HTTP以外の自前のものに書き換える事 ができる (e.g. mod_ssl)
    • 82. AboutConnection Cycle PerlPreConnectionHandler PerlProcessConnectionHandler ※「Practical mod_perl」より抜粋
    • 83. Why I want to write SMTP server by perl• DB引きたい• 絵文字処理したい• 通常のMTA(Sendmail/qmail/Postfix等)の pipeではスケールできない
    • 84. Qpsmtpd• http://smtpd.develooper.com/• 実際に私(会社)もmod_perl2 Connection cycleでSMTPサーバを実装してみたもの の、既にPerl界隈にはQpsmtpdという MTAがある
    • 85. Qpsmtpd has some Engine=Transport• pipe (CGI like)• fork-server• prefork-server• Apache (Apache::Qpsmtpd)• async (Danga::Socket base)
    • 86. Qpsmtpd’s Apache::Qpsmtpd• Apache2 / mod_perl2 の Connection cycle の良い応用例• これを見るとApache2をEngineとして MTAを作る方法が良く分かる
    • 87. Other topics
    • 88. Test of mod_perl handler• 「モダンPerl入門」に詳しく書いてある• Apache2::FakeRequestを使って偽物の$r を作ってハンドラをテストできる• 処理単位のテストはTest::More等で• 詳しくは割愛、もしくは上述の書籍を
    • 89. nginx: HttpPerlModulehttp://wiki.nginx.org/HttpPerlModule
    • 90. nginx: HttpPerlModule• 構文や考え方がmod_perl1と酷似 →mod_perlの知識を流用可能• ただしイベント駆動サーバならではの 各種制限もあるので注意• 世間での応用例も少し出てきている• 以前はEmbeddedPerlModuleという 名前だった(1.0→1.2で名称変更?)
    • 91. 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 より
    • 92. nginx: HttpPerlModule• mod_perl2ではなくmod_perl1の構文の 影響を強く受けている ($r->send_http_headers()等に見られる)• nginx設定ファイルの書き方については 割愛→前述のWikiに詳細がある
    • 93. 割愛したこと• Perl CGIの高速化環境の詳細• Apache2.4環境でのmod_perl→現時点 (2012/09)で正式にサポートしていない• Apache2.4 event MPM環境での mod_perl→上記同様
    • 94. これからのApache• Apache2.4でmod_perlがサポートされた ら、event MPM上でmod_perl動かしたい• Apacheはこれからも進化していきます• mod_lua, mod_sedがApache2.4でコアモ ジュール入り、しかしExperimental扱い
    • 95. Questions?
    • 96. ご清聴ありがとうございました