我使用AnyEvent(用于研究)创建memcached客户端并实现以下代码:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
use Carp qw/croak carp/;
use AnyEvent;
use AnyEvent::Handle;
use AnyEvent::Socket;
use EV;
sub get {
my ($host, $port, $cv, $keys, %args) = @_; # $args -> cb => sub {$value, $err}
$cv->begin if $cv;
tcp_connect $host => $port, sub {
my $fh = shift or die "unable to connect: $!";
my $handle;
$handle = new AnyEvent::Handle
fh => $fh,
on_error => sub {
my ($handler, $fatal, $msg) = @_;
AE::log error => $msg;
$handler->destroy;
$cv->send;
},
on_eof => sub {
$handle->destroy; # destroy handle
AE::log info => "Done.";
$cv->send;
};
my $array = 1 if ref $keys and ref $keys eq 'ARRAY';
my $key = $array
? 'get ' . join(' ', @$keys) . "\r\n"
: "get $keys\r\n";
$cv->begin;
$handle->push_write($key);
my $result;
my $reader; $reader = sub {
my ($handle, $line) = @_;
if ($line eq 'END') {
undef $reader;
$args{cb}($result);
}
elsif (substr($line, 0, 5) eq 'ERROR') {
undef $reader;
$args{cb}(undef, $line);
}
elsif (!length($line)) {
warn "Skip empty line";
$handle->unshift_read(line => $reader);
}
elsif($line =~ /^VALUE (\S+) (\d+) (\d+)(?:| (.+))$/ ) {
my ($key, $flags, $len, $cas) = ($1, $2, $3, $4);
$handle->push_read(chunk => $len+2, sub { # data length + \r\n
my ($handle, $data) = @_;
substr($data, $len) = ''; # trim \r\n
if ($array) {
$result->{$key} = $data;
} else {
$result = $data;
}
$handle->unshift_read(line => $reader);
$cv->send;
});
}
};
$handle->push_read(line => $reader);
$cv->end;
}, sub { 30; };
}
my $cv = AnyEvent->condvar;
my $host = '127.0.0.1';
my $port = 11211;
get($host, $port, $cv, 'data', cb => sub {
my ($value, $err) = @_;
$err and return warn "Get failed: @_";
warn "Value for key is '$value'";
});
get($host, $port, $cv, [qw/data someKey/], cb => sub {
my ($values, $err) = @_;
$err and return warn "Get failed: @_";
warn "Value for key1 is '$values->{data}' and value for key2 is '$values->{someKey}'";
});
$cv->recv;
但由于某些原因,这段代码不稳定。输出:
$ perl test_anyevent.pl
Value for key1 is 'hello memcached world' and value for key2 is 'hello world' at test_anyevent.pl line 95.
Value for key is 'hello memcached world' at test_anyevent.pl line 89.
$ perl test_anyevent.pl
Value for key1 is 'hello memcached world' and value for key2 is 'hello world' at test_anyevent.pl line 95.
$ perl test_anyevent.pl
Value for key1 is 'hello memcached world' and value for key2 is 'hello world' at test_anyevent.pl line 95.
Value for key is 'hello memcached world' at test_anyevent.pl line 89.
$ perl test_anyevent.pl
Value for key1 is 'hello memcached world' and value for key2 is 'hello world' at test_anyevent.pl line 95.
Value for key is 'hello memcached world' at test_anyevent.pl line 89.
我不知道为什么'得'命令一个工作,然后两个。如果我使用模块AnyEvent :: Memcached,那么一切都很好:
#!/usr/bin/perl -w
use strict;
use warnings;
use feature 'say';
use AnyEvent;
use EV;
use AnyEvent::Memcached;
my $cv = AnyEvent->condvar;
my $memd = AnyEvent::Memcached->new(
servers => ['127.0.0.1:11211'],
cv => $cv,
);
$memd->get('data', cb => sub {
my ($value, $err) = shift;
$err and return warn "Get failed: @_";
warn "Value for key is $value";
});
$memd->get([qw/data someKey/], cb => sub {
my ($values, $err) = shift;
$err and return warn "Get failed: @_";
warn "Value for key1 is '$values->{data}' and value for key2 is '$values->{someKey}'";
});
$cv->recv;
输出:
$ perl anyevent_memcached_mons.pl
Value for key is hello memcached world at anyevent_memcached_mons.pl line 20.
Value for key1 is 'hello memcached world' and value for key2 is 'hello world' at anyevent_memcached_mons.pl line 26.
$ perl anyevent_memcached_mons.pl
Value for key is hello memcached world at anyevent_memcached_mons.pl line 20.
Value for key1 is 'hello memcached world' and value for key2 is 'hello world' at anyevent_memcached_mons.pl line 26.
$ perl anyevent_memcached_mons.pl
Value for key is hello memcached world at anyevent_memcached_mons.pl line 20.
Value for key1 is 'hello memcached world' and value for key2 is 'hello world' at anyevent_memcached_mons.pl line 26.
无法理解可能出现什么问题?