在实际使用中,并行的请求内部很有可能有顺序的要求.比如按设备并行,同一设备按snmp采集的oid串行.
使用anyevent::snmp的嵌套回调,很快就会让人疯掉.
借助coro无疑是比较好的方'案,但是在一些简单的场合,也可以使用Anyevent::Delay或者Anyevent::Delay::simple,来实现顺序请求.
原本嵌套的回调可以写成并列的函数.同时可以传递参数.可以实现比较简单的顺序要求.
#!/usr/bin/perl
#测试anyevent::snmp 并发+串行(按设备并发,按oid串行,不能有复杂分支)
use 5.014;
use AnyEvent;
use AnyEvent::SNMP;
use Net::SNMP;
use AnyEvent::Delay::Simple qw(delay);
my $cocurrent = 50; # 并发数
#my @todoList = map { "192.168.6." . $_ } (1 .. 100); #
my @todoList = ("192.168.6.87","192.168.6.25","192.168.6.46"); #
my $oid=".1.3.6.1.2.1.1.1.0"; #sysDescr
my $oid1=".1.3.6.1.2.1.1.7.0"; #sysDescr
my $cv = AnyEvent->condvar;
doit() foreach 1..$cocurrent;
sub doit{
my $ip = shift @todoList;
return if not defined $ip;
$cv->begin;
# my $oid=".1.3.6.1.2.1.1.7.0";
# my @oids=($oid);
print "$ip.\n";
my $sess=Net::SNMP->session (-hostname => $ip,
-community => "public",
-timeout => 1,
-nonblocking => 1,
-translate => [-timeticks => 0x0]
);
delay([
sub{
my $cv = shift();
$cv->begin();
$sess->get_request (
-varbindlist => [ $oid ],
-callback => sub {
my ($session) = @_;
my $result = $session->var_bind_list();
if (!defined $result) {
printf "ERROR: Get request failed for host '%s': %s.\n",
$session->hostname(), $session->error();
#die();#在回调函数里面die是没用的
$cv->send(-1);
}
else{
printf "The sysDescr for host(%s) '%s' is %s.\n",$ip,
$session->hostname(), $result->{$oid};
}
$cv->send( $result->{$oid});
}
);
},
sub{
my ($cv, @args) = @_;
print ("2nd oid.(@args).\n");
$cv->begin();
$sess->get_request (
-varbindlist => [ $oid1 ],
-callback => sub {
my ($session) = @_;
my $result = $session->var_bind_list();
if (!defined $result) {
printf "ERROR: Get request failed for host '%s': %s.\n",
$session->hostname(), $session->error();
#die();
$cv->send(-1);
}
else{
printf "The sysUptime for host(%s) '%s' is %s.\n",$ip,
$session->hostname(), $result->{$oid1};
}
$cv->send( $result->{$oid1});
}
);
}],
sub { # calls on error, at this time
print('Fail: ' . $_[1]);
$cv->end();
&doit();
},
sub { # calls on success, not at this time
my ($v, @args) = @_;
print("Ok(@args).\n");
$cv->end();
&doit();
}
); #delay
}
$cv->recv();