any event intro

27
AnyEvent介绍 Achilles Xu [email protected] 11年7月4日星期一

Upload: qiang

Post on 08-May-2015

2.081 views

Category:

Technology


0 download

DESCRIPTION

From Beijing Perl Workshop 2011 http://conference.perlchina.org/bjpw2011/

TRANSCRIPT

Page 1: Any event intro

AnyEvent介绍Achilles Xu

[email protected]

11年7月4日星期一

Page 2: Any event intro

Contents简介

Hello World

Watcher

CondVar

参数传递

工具模块

封装

Bugs

11年7月4日星期一

Page 3: Any event intro

丫是啥?

一个异步框架,支持多种底层驱动

EV, libevent, POE, Glib, QT, Tk

11年7月4日星期一

Page 4: Any event intro

Hello Worlduse AnyEvent;

my $cv = AnyEvent->condvar;

my $w = AnyEvent->timer(

'after' => 5,

'cb' => sub {

print "hello world\n";

$cv->send;

}

);

$cv->recv;

11年7月4日星期一

Page 5: Any event intro

元素介绍watcher

I/O

timer

signal

child process

idle

condvar

工具模块

AnyEvent::Handle

AnyEvent::DNS

AnyEvent::Socket

11年7月4日星期一

Page 6: Any event intro

I/O Watcher use AnyEvent;

$| = 1; print "enter your name> ";

my $name;

my $wait_for_input = AnyEvent->io ( fh => \*STDIN, # which file handle to check poll => "r", # which event to wait for ("r"ead data) cb => sub { # what callback to execute $name = <STDIN>; # read it } );

# do something else here

11年7月4日星期一

Page 7: Any event intro

Timer Watcher

my $once_per_second = AnyEvent->timer ( after => 0, # first invoke ASAP interval => 1, # then invoke every second cb => sub { # the callback to invoke print "hi\n"; }, );

11年7月4日星期一

Page 8: Any event intro

Watcher变量的作用域

Watcher变量超出作用域以后,会被注销

11年7月4日星期一

Page 9: Any event intro

Watcher变量的作用域use AnyEvent;

sub aaa {

my $w = AnyEvent->Timer(

after => 3,

interval => 5,

cb => sub { print "hello\n"; }

);

}

my $cv = AnyEvent->condvar;

aaa();

$cv->recv; # won't print hello every 5 seconds.11年7月4日星期一

Page 10: Any event intro

Watcher变量的作用域use AnyEvent;

my $w; # 把Watcher变量存储在外层作用域

sub aaa {

$w = AnyEvent->Timer(

after => 3,

interval => 5,

cb => sub { print "hello\n"; }

);

}

my $cv = AnyEvent->condvar;

aaa();

$cv->recv; # will print hello every 5 seconds.

11年7月4日星期一

Page 11: Any event intro

Watcher变量的作用域use AnyEvent;

sub aaa {

# 用闭包保存watcher变量

my $w; $w = AnyEvent->Timer(

after => 3,

interval => 5,

cb => sub { print "hello\n"; $w; }

);

}

my $cv = AnyEvent->condvar;

aaa();

$cv->recv; # will print hello every 5 seconds.

11年7月4日星期一

Page 12: Any event intro

Watcher变量的作用域use AnyEvent;

sub aaa {

my $w; $w = AnyEvent->timer(

after => 5,

cb => sub {

print "hello\n";

undef $w;

});

}

aaa();

AnyEvent->condvar()->recv();

11年7月4日星期一

Page 13: Any event intro

CondVar

启动main loop,类似POE::Kernal->run();

同步点控制,类似$thread->join();

“This module is an AnyEvent user, you need to make sure that you use and run a supported event loop.”

11年7月4日星期一

Page 14: Any event intro

CondVaruse AnyEvent;

my $w = AnyEvent->timer(

after => 0,

interval => 5,

cb => sub {

print "hello\n";

}

);

my $cv = AnyEvent->condvar;

$cv->recv; # just like while (1) {...}

11年7月4日星期一

Page 15: Any event intro

CondVaruse AnyEvent;

use AnyEvent::HTTP;

# 顺序执行一些操作...

my @cvs;

for (1 .. 5) {

my $cv = AnyEvent->condvar; # like thread id

push @cvs, $cv;

http_get("http://some_url", sub {

$cv->send; # like return in thread func

});

}

$_->recv for @cvs; # like $_->join for @threads;

# 继续顺序执行一些操作...

11年7月4日星期一

Page 16: Any event intro

参数传递

闭包(closure)是唯一方式

PP(Par::Packer)打包时会产生很警告

perl -T

11年7月4日星期一

Page 17: Any event intro

参数传递

use AnyEvent;

my $x = "Tom";

AnyEvent->timer(afer => 5, cb => sub {

print "hello $x";

}

11年7月4日星期一

Page 18: Any event intro

工具模块use AnyEvent;

use AnyEvent::Handle; my $cv = AnyEvent->condvar; my $hdl; $hdl = new AnyEvent::Handle fh => \*STDIN, on_error => sub { my ($hdl, $fatal, $msg) = @_; warn "got error $msg\n"; $hdl->destroy; $cv->send; }; # send some request line $hdl->push_write ("getinfo\015\012"); # read the response line $hdl->push_read (line => sub { my ($hdl, $line) = @_; warn "got line <$line>\n"; $cv->send; }); $cv->recv;

11年7月4日星期一

Page 19: Any event intro

工具模块use AnyEvent;

use AnyEvent::HTTP;

my $cv = AnyEvent->condvar;

http_get("http://www.sina.com.cn", # 不存在watcher作用域问题

sub {

my ($data, $headers) = @_;

print $headers->{Status}, "\n";

print $data, "\n";

$cv->send;

});

$cv->recv;

11年7月4日星期一

Page 20: Any event intro

工具模块use AnyEvent; # not AE

# file handle or descriptor readable my $w = AE::io $fh, 0, sub { ... };

# one-shot or repeating timers my $w = AE::timer $seconds, 0, sub { ... }; # once my $w = AE::timer $seconds, $interval, sub { ... }; # repeated

print AE::now; # prints current event loop time print AE::time; # think Time::HiRes::time or simply CORE::time. my $cv = AE::cv;

11年7月4日星期一

Page 21: Any event intro

封装

顺序完成几个步骤,然后调用传入的回调函数

并发做几件事,全部完成后调用传入的回调函数

以上二者结合

状态数据隐藏在封装函数的内部

适用于所有异步消息框架的封装

11年7月4日星期一

Page 22: Any event intro

封装http_get_retry("http://www.sina.com.cn",

max_retries => 3,

sub {

my ($data, $headers) = @_;

if (defined $data) {

print "load ok";

} else {

print "try 3 times failed";

}

});

11年7月4日星期一

Page 23: Any event intro

封装http_get_file("http://aaa.com/somefile.tar.gz",

"/data/files/somefile.tar.gz",

max_concurrent => 20,

sub {

my ($data, $headers) = @_;

if (defined $data) {

print "download ok";

} else {

print "some error happens: " . $headers->{Status};

}

});

11年7月4日星期一

Page 24: Any event intro

封装

http_get( $url, sub { ... });

DNS Resolving

TCP Connecting

Sending Request

Reading Response

11年7月4日星期一

Page 25: Any event intro

Bugs

多进程侦听socket

accept后使用push_read

rtimeout有时会瞬间出发

驱动:EV、PurePerl

单进程时不会发生

11年7月4日星期一

Page 26: Any event intro

Bug's Solution

超时回调中做补差timer

*AE::now = sub { return AE::time; }

*AE::now = *AE::time doesn't work

11年7月4日星期一

Page 27: Any event intro

谢谢

Questions?

11年7月4日星期一