Chinaunix

标题: perl Coro疑问? [打印本页]

作者: bio_tt    时间: 2013-01-07 20:28
标题: perl Coro疑问?
本帖最后由 bio_tt 于 2013-01-07 20:44 编辑

  hi,最近在用Coro ,有的地方不是特别理解。希望指导一下:


  #!/usr/bin/perl -w

use Coro;
my @coro;
foreach my $i(4..6)
{
   &doit($i);
}

sub doit()
{
   my $time=shift;
   push @coro,async{
    print "$time begin\n";
    sleep($time);
    print "$time end\n";
   };
}

$_->join foreach(@coro);

上面的脚本最终运行时间为4+5+6=15s,为啥在async{}里面没有并行啊,如果用threads就可以。

求指导!

PS: 是不是Coro只有跟支持异步的或者事件结合才能发挥作用,例如Coro+AnyEvent:: Ping  与 AnyEvent+AnyEvent:: Ping一样?而与Coro+Net:: Ping不一样?

作者: zhlong8    时间: 2013-01-08 10:29
Coro 只在一个线程运行, sleep 这类阻塞操作是不能用的,要用 Coro 提供的非阻塞的才行。而且单纯的 Coro 只是协程当前 coro 放弃CPU别的才有机会执行,多少秒后执行这种事没太大意义
作者: bio_tt    时间: 2013-01-08 11:19
回复 2# zhlong8

好的,版主,我最近在尝试用AnyEvent+IO::Socket写支持多客户段连接,模仿select,但是一直没成功,你帮我看下吧。谢谢了。


    #!/usr/bin/perl -w
use IO::Socket;
use AnyEvent;

my $socket=IO::Socket::INET->new(
LocalAddr=>"127.0.0.1",
LocalPort=>"9000",
Type=>SOCK_STREAM,
Proto=>'tcp',
Listen=>20,
Blocking=>0
) or die " socket can not create $@";

$socket->autoflush(1);

my $cv=AnyEvent->condvar;
my $wait=AnyEvent->io(
fh=> $socket,
poll=>"r",
cb=>sub {
   $cv->begin;
   $new=$socket->accept;
  while(<$new>)
   {
      print $_;
   }
   close($new);
  $cv->end;
}
);

$cv->recv;

1. 发现只有一个客户可以连接,然后发送消息,其他客户不行。怎样才能保证这个服务就像服务端一样,一直在监听中?
2. 怎样保证多个客户可以同时连接,然后发送消息呢?
作者: py    时间: 2013-01-09 07:38
你至少要先明白Coro是个什么东西,有什么特点。这样才能更快理解和使用它。不想明白就开始写代码实验,对Coro不太可行。
Coro的“线程”并不是通过并行运行多个任务而实现4+5+6=6. 而是通过节省阻塞时间实现的。
对于你的代码,把sleep换成Coro::AnyEvent::sleep $time就可以了,需要use Coro::AnyEvent模块。

作者: laputa73    时间: 2013-01-09 08:52
回复 4# py
象perl/python这类非原生支持协程的语言
常犯的错误就是引入了阻塞的方法
这个新人很难避免啊
基本上用到io,network相关的方法都要去看看有没有coro对应的模块
网上的例子也不多.
而且以前的很多模块都不能用了.
需要用coro模块重写.
想听听版主在生产环境中使用coro的经验


   
作者: hansion3406    时间: 2013-01-09 10:25
楼主高人啊,我先收藏了
作者: py    时间: 2013-01-09 12:54
回复 5# laputa73

AnyEvent的相关非阻塞模块已经比较丰富,即使没有找到,有了AnyEvent::Socket也可以创造一切了。
以前我也觉得“例子太少”,后来慢慢明白,CPAN上作者提供的那些例子已经足够了。剩下的就要靠自己了。所谓“靠自己”就是在理解文档以后,不断思考和尝试。但这不符合中国技术人的行为方式,总是希望做什么都有个很现成的例子看看改改抄抄。

我在生产环境用Coro主要是发SOAP请求,简单的说就是从WEB上接收发送任务,用Coro,AnyEvent::HTTP等进行批量发送。
其实很多简单的Coro的功能AnyEvent也都能完成,但Coro的重要功能是协程,在系统变得复杂的时候这些功能就发挥重要作用了。
   
作者: bio_tt    时间: 2013-01-09 13:56
回复 5# laputa73


  版主,我尝试用AnyEvent+IO::Socket 模仿select已经很久了,但是最后还是无法支持,多个客户端发送消息以后立即显示。。
  
  我知道有个AnyEvent::Socket模块,但是我想自己写,所以希望就上面的代码给个建议。 谢谢. :wink:
   
作者: laputa73    时间: 2013-01-09 14:25
coro的非阻塞比较适合做server或者app
比方说它的DBI实现是通过fork一个子进程实现dbi连接,这样主进程就可以实现无阻塞
这种方式作单进程server,连少数数据库是没 问题的
但是如果是做client,要连大量的数据库,就不行了。
ping和http比较简单
其他的真的就得靠AnyEvent::Socket来创造了
作者: laputa73    时间: 2013-01-09 16:10
本帖最后由 laputa73 于 2013-01-10 08:22 编辑

回复 8# bio_tt
我知道你的意思
因为前两天 我刚看了lua编程设计的协程一节,它就是用的select而不是异步io
用coro:socket应该是可以实现的
coro+io::socket不知道是否可行,需要实际测试一下
它的思路就是settimeout(0)
遇到阻塞(超时)就切换协程yield
在主进程要用select检查是否有新信息
用coro::socket应该就可以省了这些




   




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2