AnyEvent + Coro ã§ã®ä¸¦è¡ãã¦ã³ãã¼ãã®ç¿ä½
AnyEvent 㨠Coro ã使ã£ã¦ãWEB ããéåæã«ä¸¦è¡ãã¦ã³ãã¼ãããããã°ã©ã ã®ç¿ä½ãä½ã£ã¦ã¿ããhttp://kaede.to/~canada/doc/wiser-clawer-sample-using-coroãã ãã¶åèã«ããã¦ããã£ã¦ãããç´¹ä»ããã¦ããéåæã¯ãã¼ã©ã¯ã¨ã¦ãããã®ã ããèªåããããã¨ãã¦ãããã¨ãèããã¨ã次ã®ç¹ãã¡ãã£ã¨æ°ã«ãªã£ãã
- 対象 URI ã®ãªã¹ãã¯ä¸åä¸ãªã¼ãã«ãªã
- ãããããã¡ã¢ãªä¸ã«åæãã¦ããã¦ããã®ã ããã
- URI ã®æ°åã®ã¹ã¬ãããèµ·ããã¦ããã®ã ããã
- åå解決ããã¨åä¸ IP ã¢ãã¬ã¹ã«ãªããã¹ããå°ãªããªã
- åæãªã¯ã¨ã¹ãå¶éããããã®ã¯ãã¹ãåã§ã¯ãªã IP ã¢ãã¬ã¹ãããã®ã§ã¯ãªãã ããã
ã¨ãããã¨ã§ã次ã®ãããªç¹å¾´ãæã¤ã¹ã¯ãªãããæ¸ãã¦ã¿ãã
- æ大åææ¥ç¶æ°ã®å¶å¾¡ã«ã¯ã»ããã©ã使ãã®ã§ã¯ãªãããã®æ° (20 ãªã 20 å) åã®ã¯ã¼ã«ã¼ã¹ã¬ãããä½ã
- ã¯ã¼ã«ã¼ã¹ã¬ãã㯠URI ãåãåã£ã¦ãã¦ã³ãã¼ããã¦ãããã¨ããã®ã延ã ç¹°ãè¿ã
- ãã ã²ãããç¡éã« URI ãçæãã URI çæã¹ã¬ãããä½ã
- å®éã«ã¯ DB ããã¡ã¤ã«ãæ¤ç´¢ã¨ã³ã¸ã³ãªã©ãä»ã®ã½ã¼ã¹ãã URI ãæã£ã¦ãããã¨ãæ³å®
- URI çæã¹ã¬ããã¨ã¯ã¼ã«ã¼ã®éã® URI ã®ããã¨ã㯠Coro::Channel ãå©ç¨
- åä¸ IP ã¢ãã¬ã¹ã¸ã®åæãªã¯ã¨ã¹ãæ°ãå¶éãã
- AnyEvent::HTTP::http_get ã§ã¯ãã¹ãåã ãã§ããåæãªã¯ã¨ã¹ãå¶éã§ããªã
- AnyEvent::DNS ãå©ç¨ãã¦éåæã«åå解決ãã
- åä¸ IP ã¢ãã¬ã¹ã¸ã®åæãªã¯ã¨ã¹ãå¶éã«ã¯ã»ããã©ãç¨ãã
use strict; use warnings; use AnyEvent; use AnyEvent::DNS; use AnyEvent::HTTP; use Coro; use Coro::Channel; use Coro::Semaphore; use URI; my $uri_channel = new Coro::Channel 5; my %semaphore_for = (); for my $i (0..19) { my $worker_t = async { while (1) { my $uri = $uri_channel->get(); my $host = URI->new($uri)->host; AnyEvent::DNS::a $host, Coro::rouse_cb; my $ip_addr = Coro::rouse_wait; if (! defined $semaphore_for{$ip_addr}) { $semaphore_for{$ip_addr} = new Coro::Semaphore 4; } my $guard = $semaphore_for{$ip_addr}->guard; print "getting $i $uri ...\n"; http_get $uri, Coro::rouse_cb; my @results = Coro::rouse_wait; print "done $i $uri.\n"; } }; } my $producer_t = async { my $base_uri = q{http://www.example.com/}; my $q = 0; while (1) { $uri_channel->put("$base_uri?q=$q"); $q++; } }; $producer_t->join;
URI çæã¹ã¬ãã ($producer_t) ã¯ç¡éã«ã¼ãã§ãhttp://www.example.com/?q=0, http://www.example.com/?q=1, http://www.example.com/?q=2 ... ã¨ãã URI ããã£ãã« $uri_channel ã«æ¼ãè¾¼ãã§ããã ãã$uri_channel ã¯ãµã¤ãº 5 ã«ãã¦ãããããã£ãã«ã® producer ãä¸ã¤ãªã®ã«å¯¾ããconsumer ã 20 åã¨ãã«ãªãã®ã§ããã£ã¨å¤§ããå¤ã«ããã»ããå¹çãããã ãããä»ã¯ç¿ä½ã§åç´ã« URI ãçæãã¦ããããå®éã«ã¯ URI ã®çæã«ãã£ã¨ã³ã¹ãããããã ããããã®çæã³ã¹ãã¨ã®å ¼ãåããèæ ®ããªããã°ãªããªãã
ã¯ã¼ã«ã¼ã¹ã¬ãã ($worker_t) 㯠20 æ¬ä½ãããã$uri_channel ãã URI ãä¸ã¤ããã£ã¦ãã¦ã¯ HTTP ãªã¯ã¨ã¹ããæãããã¨ããç¡éã«ã¼ããèµ°ãããã£ãã«ããã® get() æãDNS ã®åå解決㨠HTTP ãªã¯ã¨ã¹ãã® 2 ç®æã® rouse_wait å®è¡æãguard ãªãã¸ã§ã¯ãã®åå¾æãã«ä»ã®ã¹ã¬ããã«å¶å¾¡ã移ãå¯è½æ§ãããã
URI çæã¹ã¬ããã ãã join ã§å¾ ã¡åãã¦ãããããã®ã¹ã¯ãªããã§ã¯ã©ã®ã¹ã¬ãããç¡éã«ã¼ãããã®ã§å¼·å¶çµäºããªãã¨çµãããªãããããã«çµããããã«ã¯ãwhile (1) ã§ç¡éã«ã¼ããã¦ããç®æã while ($keep) ã¨ãã«ãã¦ãã©ãã㧠$keep ãã©ã°ãè½ã¨ãããã«ããã°ãããããããªãã
å®è¡çµæã¯æ¬¡ã®ããã«ãªã£ãã
$ perl async.pl getting 0 http://www.example.com/?q=0 ... getting 1 http://www.example.com/?q=1 ... getting 2 http://www.example.com/?q=2 ... getting 3 http://www.example.com/?q=3 ... done 0 http://www.example.com/?q=0. getting 4 http://www.example.com/?q=4 ... done 1 http://www.example.com/?q=1. getting 5 http://www.example.com/?q=10 ... done 2 http://www.example.com/?q=2. getting 6 http://www.example.com/?q=11 ... done 3 http://www.example.com/?q=3. getting 7 http://www.example.com/?q=12 ... done 5 http://www.example.com/?q=10. ...
追è¨
ã»ããã©ã®æ°ãæ¥ç¶ãããã¨ã®ãã IP ã¢ãã¬ã¹ã®æ°ã¨åãã ãå¿ è¦ãªã®ãããã ããªããä»ã®é¨åã¯ãã¼ã¿éã«ãããã¡ã¢ãªæ¶è²»ã¯ä¸å®ãªã®ã«ãã»ããã©ã¯ãã¼ã¿éã«æ¯ä¾ãã¦ã¡ã¢ãªãé£ã£ã¦ãã¾ããåæã«ã¯ãããã ã 20 åãã並åã§åããªãã®ã§ãç¾å¨æ¥ç¶ä¸ã® IP ã¢ãã¬ã¹ã¨æ¯ã¹ã¦æ¥ç¶ãããå¦ãã決å®ããããã«ããã°ããã®ãããããªãã