Upgrade to Pro — share decks privately, control downloads, hide ads and more …

モダンmod_perl入門 #yapcasia

OGATA Tetsuji
September 29, 2012

モダンmod_perl入門 #yapcasia

2012/09/29 に YAPC::Asia Tokyo 2012 で発表したスライドです。

OGATA Tetsuji

September 29, 2012
Tweet

More Decks by OGATA Tetsuji

Other Decks in Technology

Transcript

  1. 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.
  2. ࣗݾ঺հ • ඌܗ మ࣍ (OGATA Tetsuji) • Twitter: @xtetsuji •

    Blog: http://post.tetsuji.jp/ • SlideShare: http://www.slideshare.net/xtetsuji • Α͘ߦ͘: Hokkaido.pm, Hachioji.pm • ಘҙٕ: mod_perl (ଞ͸Α͘஌Βͳ͍)
  3. 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
  4. If time is left • Compare with others • Connection

    cycle: Let’s make SMTP Server by mod_perl • Other topics
  5. ࢀߟจݙ • ༸ॻʹͳΓ·͕͢ɺ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/)
  6. History of mod_perl • mod_perl1 fi rst public release: 1996/3/25

    (see: http://perl.apache.org/dist/mod_perl-1.0-current/Changes) • mod_perl2 fi rst public release: 2002/4/6 (see: http://perl.apache.org/dist/mod_perl-2.0-current/Changes)
  7. • mod_perl1 • mod_perl2 • ͜͏ॻ͘͜ͱͰɺ֦ுࢠ”.pl”ͷPerl CGI ͕ߴ଎Խ͢Δ (Registry→PerlRunͰ΋Մ) Perl

    CGI ͷߴ଎Խ AddHandler perl-script .pl PerlHandler Apache::Registry AddHandler perl-script .pl PerlResponseHandler \ ModPerl::RegistryPrefork # ↓Apache Con fi gurations
  8. mod_perl essence is extension of Apache • mod_perl ͷ Perl

    CGIߴ଎Խ؀ڥͰ͸ɺ HTTPϦΫΤετΛड͚ͯϨεϙϯεΛ ฦ͢͜ͱ͕ग़དྷΔͷ͸प஌ͷ௨Γ • mod_perl͸HTTPϨεϙϯεΛฦ͚ͩ͢ Ͱͳ͘ɺͦͷલॲཧ΍ޙॲཧ΋Ͱ͖Δ
  9. Apache internal • ϦΫΤετΛड͚Δ • ϔομΛղੳ͢Δ • ඞཁʹԠͯ͡URLΛม׵ͨ͠ΓɺDocumentRootΛख͕͔Γʹ࣮ύε ΛׂΓग़͢ •

    ΞΫηε੍ޚɺೝূɺঝೝ(BASICೝূͳͲ) • MIMEλΠϓΛߟ͑Δ • ϨεϙϯεΛग़͢(੩తϑΝΠϧɺϓϩάϥϜग़ྗ) • ϩά(ΞΫηεϩάɺΤϥʔϩά)Λग़ྗ͢Δ • ࣍ͷϦΫΤετΛ଴ͭ
  10. 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/con fi g.html#toc_Perl_Handlers
  11. 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/con fi g/con fi g.html
  12. fi rst 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;
  13. fi rst mod_perl2 handler package 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;
  14. Apache{1,2} con fi gs # Apache1 <Location /> SetHandler perl-script

    PerlHandler MyApache1::Hello </Location> # Apache2 <Location /> SetHandler modperl PerlResponseHandler MyApache2::Hello </Location>
  15. fi rst mod_perl handler • શͯ͸ sub handler ͱ $r

    ͷड͚औΓ͔Β • ͜Ε͸ͲͷॲཧϑΣʔζͰ΋ಉ༷ • mod_perl2 Ͱ͸ $r ͷϝιου܈͕֤छ ผύοέʔδͰ؅ཧ͞Ε͍ͯΔͨΊɺ ϝιουʹΑͬͯࣄલʹద੾ͳ Apache2::* Λ use ͓ͯ͘͠ඞཁ͕͋Δ
  16. fi rst mod_perl handler • PerlHandler / PerlResponseHandler ʹϋϯ υϥΛηοτ͓͚ͯ͠͹ɺશͯͷϑΝ

    ΠϧͷॲཧΛϑοΫͰ͖ΔͷͰɺ*.html ϑΝΠϧ౳Λ͔͋ͨ΋ಁաతʹॲཧ͢ Δ͜ͱ͕Ͱ͖Δ → ֆจࣈॲཧͳͲ
  17. Apache1 URI Trans package 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;
  18. Apache2 URI Trans package 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;
  19. Apache{1,2} con fi gs # Apache1 # e.g. In <VirtualHost>

    Directive PerlTransHandler MyApache1::Trans # Apache2 # e.g. In <VirtualHost> Directive PerlTransHandler MyApache2::Trans
  20. mod_perl URI Trans cons than mod_rewrite • ෳ਺ͷϑΝΠϧ؅ཧ͕ඞཁͱͳΔ(*.pm) • Perl/mod_perl͕෼͔Βͳ͍୲౰ऀ΁ͷ

    Ҿ͖ܧ͕͗೉͘͠ͳΔ • Directory Context(<Location>, .htaccess) ʹॻ͔Εͨmod_rewriteઃఆͷ৔߹͸ɺ ผ్έΞ͕ඞཁͳέʔε΋͋Δ
  21. PHP pathetic story of Perl Monger • ୭͔͕ൃ஫ͨ͠ΞϓϦ͕PHP੡Ͱɺطʹ উखʹೲ඼ͪ͠Ό͍ͬͯΔ •

    ֖Λ։͚Δͱ࣮૷ͱ͔͕ςΩτ΢ա͗ • ܖ໿΍ॾʑͷཧ༝ͰखΛೖΕΒΕͳ͍ • ӡ༻୲౰ͰPerl͔͠஌Βͳ͍Զ͕PHPͷ σόοάͱ͔…
  22. package MyApache2::Auth; use strict; use warnings; # $r->headers_in() and $r->headers_out()

    returns APR::Table use 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; } } 1; # e.g. In <VirtualHost> Directive PerlAccessHandler MyApache2::Auth
  23. Request output fi lter and PHP • PHPͷग़ྗΛϑΟϧλ͢Δ • Apache2ͷωΠςΟϒϑΟϧλͳͷͰɺ

    PHPͷ ob_*() (output buffering) ౳ͷઃఆ ʹҰ੾Өڹ͞Εͳ͍ • Ԡ༻ྫ: ֆจࣈม׵ɺPHPͰॻ͖͖Εͳ ͍෦෼ΛޙͰஔ׵͢Δɺ౳ʑ
  24. Requets output fi lter practice • Filter ͷ৔߹ sub handler

    { ... } ͸ $r (Request Object)Ͱ͸ͳ͘ɺ $f (Filter Object) ΛୈҰҾ਺ʹड͚औΔ • PerlOutputFilterHandler σΟϨΫςΟϒ • ࠓճ͸վߦΛআڈ͢Δ؆୯ͳαϯϓϧ Λ঺հ
  25. 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/[\r\n]//g; $f->print($buffer); } return Apache2::Const::OK; } 1; # e.g. In <VirtualHost> Directive <FilesMatch “.*(html?|php)$”> PerlOutputFilterHandler MyApache2::FilterObfuscate </FilesMatch>
  26. Apache worker MPM and Perl ithreads • Apache worker MPM:

    εϨου(pthread) ͱϓϩηεͷϋΠϒϦοτಈ࡞ • Perl ithreds: ݏΘΕऀ • ಉ࣌ฒߦॲཧ͢ΔͳΒParallel::Prefork ౳΍AnyEventΛ࢖͏ͷ͕ࠓͷPerlྲّྀ
  27. Instruction worker MPM & mod_perl • worker MPM্Ͱͷmod_perlͷϊ΢ϋ΢ ͸ಛʹগͳ͍ͷͰϋϚΔͱةݥ •

    PerlͷεϨου͸ෆ҆ఆͰ͋ΔࣄΛ৺ಘ ্ͨͰɺෳࡶͳࣄ͸ͤͯ͞͸͍͚ͳ͍
  28. 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;
  29. 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 { ... } ... ###
  30. Queue server by mod_perl2 thread (3) ### continued sub 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;
  31. worker MPM and perl ithreads practice • ෳࡶͳࣄ͸ͤͯ͞͸͍͚ͳ͍ • ෳࡶͳࣄΛͤ͞Δ৔߹ʹ͸े෼ࢼݧΛ

    • େࣄͳ͜ͱͳͷͰ(ry • લग़ͷQueue server͸100KBఔ౓ͷจࣈ ྻͷೖग़ྗΛ10K/minͤͯ͞΋໰୊ແ͠
  32. mod_{lang} (1) • mod_perl: ࠷΋ྺ࢙͕ݹ͍΋ͷͷҰͭ • mod_ruby: ։ൃఀ଺ঢ়ଶˠmod_mruby • mod_python:

    ։ൃఀ଺ঢ়ଶ • mod_lua: Apache2.4͔ΒίΞϞδϡʔϧ • mod_mruby: 2012೥4݄ʹొ৔͠׆ൃ
  33. mod_{lang} (2) • mod_wsgi: Python WSGI ࣮૷ • mod_php: ͍ΘΏΔPHP

    • ͪ͜Β͸ࠓ·ͰͷҙຯͰApacheΛ ʮ֦ுʯ͢Δ΋ͷͰ͸ͳ͍ • ଞʹ΋ͨ͘͞Μmod_{lang}͸͋ΔΒ͍͠
  34. In future my activities • ࠓޙ΋mod_perlք۾Λ੝Γ্͍͛ͨ • TwitterΞΧ΢ϯτ࡞ͬͨ @mod_perl_info •

    ΢ΣϒαΠτ΋࡞੒த(ະ׬੒) http://modperl.info/ • ৄࡉɺׂѪͨ͠෦෼ͷଓ͖͸Ͳ͔͜Ͱ
  35. Why I want to write SMTP server by perl •

    DBҾ͖͍ͨ • ֆจࣈॲཧ͍ͨ͠ • ௨ৗͷMTA(Sendmail/qmail/Post fi x౳)ͷ pipeͰ͸εέʔϧͰ͖ͳ͍
  36. Qpsmtpd has some Engine=Transport • pipe (CGI like) • fork-server

    • prefork-server •Apache (Apache::Qpsmtpd) • async (Danga::Socket base)
  37. Qpsmtpd’s Apache::Qpsmtpd • Apache2 / mod_perl2 ͷ Connection cycle ͷྑ͍Ԡ༻ྫ

    • ͜ΕΛݟΔͱApache2ΛEngineͱͯ͠ MTAΛ࡞Δํ๏͕ྑ͘෼͔Δ
  38. nginx: HttpPerlModule package 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 ΑΓ