免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4268 | 回复: 16
打印 上一主题 下一主题

请教一下coro多线程抓网页的例子。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-07-16 14:54 |只看该作者 |倒序浏览
刚开始学coro,不太熟悉
请教一下coro多线程抓网页的例子。
coro在碰见线程阻塞会自动调度到其他线程吗,还需要手工cede吗?
  1. #!/usr/local/bin/perl
  2. #测试多个anyevent:http函数的处理
  3. use strict;
  4. use Coro;
  5. use AnyEvent::HTTP;


  6.   my $coro1 = async {
  7.          
  8.             http_get ("http://www.baidu.com/s?wd=1", cb => Coro::rouse_cb );
  9.             my ($content, $hdr) = Coro::rouse_wait;
  10.             print "1.$hdr->{Status}.\n";
  11.             http_get ("http://www.baidu.com/s?wd=2", cb => Coro::rouse_cb );
  12.             ($content, $hdr) = Coro::rouse_wait;
  13.       print "2.$hdr->{Status}.\n";
  14.       return 3;
  15.    };
  16.    
  17.   my $coro2 = async {
  18.             http_get ("http://www.baidu.com/s?wd=a", cb => Coro::rouse_cb );
  19.             my ($content, $hdr) = Coro::rouse_wait;
  20.             print "a.$hdr->{Status}.\n";
  21.             http_get ("http://www.baidu.com/s?wd=b", cb => Coro::rouse_cb );
  22.             ($content, $hdr) = Coro::rouse_wait;
  23.       print "b.$hdr->{Status}.\n";
  24.       return 4;
  25.    };
  26.    my $result = $coro1->join;
  27.    print "$result.\n";
  28.    $result = $coro2->join;
  29.    print "$result.\n";

  30. #-bash-3.00$ perl coro8.pl
  31. #1.200.
  32. #2.200.
  33. #3
  34. #a.200.
  35. #b.200.
  36. #4
  37. #-bash-3.00$
复制代码
我这么写,从结果看还是串行的,请教一下正确的写法?

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2012-07-17 09:34 |只看该作者
1. 会的。所以不需要cede
2. 你没写错。最多就是不太合理而已。

你所看到的“结果”,说明:“按照join的顺序得到了结果”。这并不意味着“一切都是串行”的。
假设你用LWP顺序获取1000个网页的结果需要1000s,你用上面你的代码运行的方式创建1000个async,只需要远小于1000s的时间。
  1. use Coro;
  2. use AnyEvent::HTTP;

  3. my @url = ('http://www.amazon.com/', 'http://www.cpan.org','http://www.google.com', 'http://www.baidu.com');

  4. my @coro;
  5. foreach my $url (@url){
  6.     push @coro, async {
  7.                 print "start $url\n";
  8.                 http_get $url, cb => Coro::rouse_cb;
  9.                 my @res = Coro::rouse_wait;
  10.                 print "end $url\n";
  11.         };
  12. };

  13. foreach (@coro) {
  14.         print "joining\n";
  15.         $_->join;
  16.         print "joined\n";
  17. };
复制代码
把每一行的输出顺序都弄明白了,Coro就学会了。
不明白就看Coro的文档(英文的)。读书千遍,其义自见。

论坛徽章:
2
CU大牛徽章
日期:2013-04-17 11:46:28CU大牛徽章
日期:2013-04-17 11:46:39
3 [报告]
发表于 2012-07-17 09:43 |只看该作者
为何不用 LWP 呢?

论坛徽章:
0
4 [报告]
发表于 2012-07-17 10:47 |只看该作者
LWP最直观,并发就fork吧,最简单

论坛徽章:
0
5 [报告]
发表于 2012-07-17 11:19 |只看该作者
回复 4# 斯文牛氓
谢谢楼上
如果用lwp,就不问了。
主要是为了学习coro和异步事件的配合
要实现高效的并发采集


   

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
6 [报告]
发表于 2012-07-17 11:24 |只看该作者
回复 3# cdtits

如果你需要在短时间内获取1千万个页面,Coro是最优方案。
LWP+fork有太多问题,退一步讲也应该是LWP+Coro
   

论坛徽章:
2
CU大牛徽章
日期:2013-04-17 11:46:28CU大牛徽章
日期:2013-04-17 11:46:39
7 [报告]
发表于 2012-07-17 13:29 |只看该作者
回复 6# py


    明白了,谢谢!

论坛徽章:
0
8 [报告]
发表于 2012-07-17 20:25 |只看该作者
回复 2# py


    多谢py的指点,正是我需要的。
   coro 的文档通读了有5,6遍吧。
   感觉和stackless python很象,比greenlet 复杂
   不过没有一个完整的例子,总还是没概念。
  
   如作者所说,coro的好处,是可以保留传统的顺序处理的逻辑,而不会被回调函数打断。
   我的想法是,单个的协程是可以被阻塞的,而不影响整体的性能。
   这样在处理并发而又有逻辑顺序的时候,就会清晰一点。

   在做抓网页和ping主机这样的简单操作还体现不出来。
   在处理snmp,telnet等需要交互的场景,就有差别了。

   BTW,Anyevent好像没有提供支持telnet/ssh的模块。
   
   

论坛徽章:
0
9 [报告]
发表于 2012-07-17 20:47 |只看该作者
本帖最后由 laputa1973 于 2012-07-17 20:57 编辑

根据py的指点,重新测试了一下
  1. use Coro;
  2. use AnyEvent::HTTP;

  3. my $url = 'http://www.baidu.com';
  4. my $cocurrent = 5;    # 并发数

  5. my @coro;

  6. foreach my $i (1..$cocurrent){
  7.     push @coro, async {
  8.                 #print "start $i\n";
  9.                 http_get $url, cb => Coro::rouse_cb;
  10.                 my @res = Coro::rouse_wait;
  11.                 print "end $i\n";
  12.                
  13.                 #print "start $i\n";
  14.                 http_get $url, cb => Coro::rouse_cb;
  15.                 my @res = Coro::rouse_wait;
  16.                 print "end2 $i\n";
  17.         };
  18. };



  19. foreach (@coro) {
  20.         print "joining\n";
  21.         $_->join;
  22.         print "joined\n";
  23. };
复制代码
输出结果和预想的一致
不同的协程,以及协程内部的多个异步http_get都是异步执行的。
join是同步执行的
  1. -bash-3.00$ perl testcoro10.pl
  2. joining
  3. end 1
  4. end 5
  5. end 2
  6. end2 1
  7. joined
  8. joining
  9. end2 2
  10. joined
  11. joining
  12. end2 5
  13. end 3
  14. end2 3
  15. joined
  16. joining
  17. end 4
  18. end2 4
  19. joined
  20. joining
  21. joined
  22. -bash-3.00$
复制代码

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
10 [报告]
发表于 2012-07-18 08:37 |只看该作者
我一般都不用join
有批量任务的时候,就直接用schedule把主线程挂起。剩下的一切就都交给Coro了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP