AnyEvent-MP
view release on metacpan or search on metacpan
securely authenticate nodes.
* The AEMP protocol is optimised for both text-based and binary
communications.
The AEMP protocol, unlike the Erlang protocol, supports both
programming language independent text-only protocols (good for
debugging), and binary, language-specific serialisers (e.g.
Storable). By default, unless TLS is used, the protocol is actually
completely text-based.
It has also been carefully designed to be implementable in other
languages with a minimum of work while gracefully degrading
functionality to make the protocol simple.
* AEMP has more flexible monitoring options than Erlang.
In Erlang, you can chose to receive *all* exit signals as messages
or *none*, there is no in-between, so monitoring single Erlang
processes is difficult to implement.
Monitoring in AEMP is more flexible than in Erlang, as one can
choose between automatic kill, exit message or callback on a
per-port basis.
* Erlang tries to hide remote/local connections, AEMP does not.
Monitoring in Erlang is not an indicator of process death/crashes,
in the same way as linking is (except linking is unreliable in
Erlang).
In AEMP, you don't "look up" registered port names or send to named
ports that might or might not be persistent. Instead, you normally
spawn a port on the remote node. The init function monitors you, and
you monitor the remote port. Since both monitors are local to the
node, they are much more reliable (no need for "spawn_link").
This also saves round-trips and avoids sending messages to the wrong
port (hard to do in Erlang).
RATIONALE
Why strings for port and node IDs, why not objects?
We considered "objects", but found that the actual number of methods
that can be called are quite low. Since port and node IDs travel
over the network frequently, the serialising/deserialising would add
lots of overhead, as well as having to keep a proxy object
everywhere.
Strings can easily be printed, easily serialised etc. and need no
special procedures to be "valid".
And as a result, a port with just a default receiver consists of a
single code reference stored in a global hash - it can't become much
cheaper.
Why favour JSON, why not a real serialising format such as Storable?
In fact, any AnyEvent::MP node will happily accept Storable as
framing format, but currently there is no way to make a node use
Storable by default (although all nodes will accept it).
The default framing protocol is JSON because a) JSON::XS is many
times faster for small messages and b) most importantly, after years
of experience we found that object serialisation is causing more
problems than it solves: Just like function calls, objects simply do
not travel easily over the network, mostly because they will always
be a copy, so you always have to re-think your design.
Keeping your messages simple, concentrating on data structures
rather than objects, will keep your messages clean, tidy and
efficient.
PORTING FROM AnyEvent::MP VERSION 1.X
AEMP version 2 has a few major incompatible changes compared to version
1:
AnyEvent::MP::Global no longer has group management functions.
At least not officially - the grp_* functions are still exported and
might work, but they will be removed in some later release.
AnyEvent::MP now comes with a distributed database that is more
powerful. Its database families map closely to port groups, but the
API has changed (the functions are also now exported by
AnyEvent::MP). Here is a rough porting guide:
grp_reg $group, $port # old
db_reg $group, $port # new
$list = grp_get $group # old
db_keys $group, sub { my $list = shift } # new
grp_mon $group, $cb->(\@ports, $add, $del) # old
db_mon $group, $cb->(\%ports, $add, $change, $del) # new
"grp_reg" is a no-brainer (just replace by "db_reg"), but "grp_get"
is no longer instant, because the local node might not have a copy
of the group. You can either modify your code to allow for a
callback, or use "db_mon" to keep an updated copy of the group:
my $local_group_copy;
db_mon $group => sub { $local_group_copy = $_[0] };
# now "keys %$local_group_copy" always returns the most up-to-date
# list of ports in the group.
"grp_mon" can be replaced by "db_mon" with minor changes - "db_mon"
passes a hash as first argument, and an extra $chg argument that can
be ignored:
db_mon $group => sub {
my ($ports, $add, $chg, $del) = @_;
$ports = [keys %$ports];
# now $ports, $add and $del are the same as
# were originally passed by grp_mon.
...
};
Nodes not longer connect to all other nodes.
In AEMP 1.x, every node automatically loads the AnyEvent::MP::Global
module, which in turn would create connections to all other nodes in
the network (helped by the seed nodes).
( run in 0.635 second using v1.01-cache-2.11-cpan-39bf76dae61 )