ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-MP/MP/Intro.pod
(Generate patch)

Comparing AnyEvent-MP/MP/Intro.pod (file contents):
Revision 1.27 by root, Sat Aug 29 16:27:50 2009 UTC vs.
Revision 1.28 by root, Mon Aug 31 11:07:58 2009 UTC

181 181
182 use AnyEvent; 182 use AnyEvent;
183 use AnyEvent::MP; 183 use AnyEvent::MP;
184 use AnyEvent::MP::Global; 184 use AnyEvent::MP::Global;
185 185
186 initialise_node "eg_simple_receiver"; 186 configure nodeid => "eg_receiver", binds => ["*:4040"];
187 187
188 my $port = port; 188 my $port = port;
189 189
190 AnyEvent::MP::Global::register $port, "eg_receivers"; 190 AnyEvent::MP::Global::register $port, "eg_receivers";
191 191
219have a few database backends, a few web frontends and some processing 219have a few database backends, a few web frontends and some processing
220distributed over a number of hosts: all of these would simply register 220distributed over a number of hosts: all of these would simply register
221themselves in the appropriate group, and your web frontends can start to 221themselves in the appropriate group, and your web frontends can start to
222find some database backend. 222find some database backend.
223 223
224=head3 C<initialise_node> And The Network 224=head3 C<configure> and the Network
225 225
226Now, let's have a look at the new function, C<initialise_node>: 226Now, let's have a look at the new function, C<configure>:
227 227
228 initialise_node "eg_simple_receiver"; 228 configure nodeid => "eg_receiver", binds => ["*:4040"];
229 229
230Before we are able to send messages to other nodes we have to initialise 230Before we are able to send messages to other nodes we have to initialise
231ourself to become a "distributed node". Initialising a node means naming 231ourself to become a "distributed node". Initialising a node means naming
232the node, optionally binding some TCP listeners so that other nodes can 232the node, optionally binding some TCP listeners so that other nodes can
233contact it and connecting to a predefined set of seed addresses so the 233contact it and connecting to a predefined set of seed addresses so the
234node can discover the existing network - and the existing network can 234node can discover the existing network - and the existing network can
235discover the node! 235discover the node!
236 236
237The first argument, the string C<"eg_simple_receiver">, is the so-called 237All of this (and more) can be passed to the C<configure> function - later
238I<profile> to use: A profile holds some information about the application 238we will see how we can do all this without even passing anything to
239that is going to be a node in an L<AnyEvent::MP> network. Customarily you 239C<configure>!
240don't specify a profile name at all: in this case, AnyEvent::MP will use
241the POSIX nodename.
242 240
243The profile allows you to set the I<node ID> that your application will 241The first parameter, C<nodeid>, specified the node ID (in this case
244use (the node ID defaults to the profile name if not specified). You can 242C<eg_receiver> - the default is to use the node name of the current host,
245also set I<binds> in the profile, meaning that you can define TCP ports 243but for this example we want to be able to run many nodes on the same
246that the application will listen on for incoming connections from other 244machine). Node IDs need to be unique within the network and can be almost
247nodes of the network. 245any string - if you don't care, you can specify a node ID of C<anon/>
246which will then be replaced by a random node name.
248 247
249You should also configure I<seeds> in the profile: A I<seed> is just a 248The second parameter, C<binds>, specifies a list of C<address:port> pairs
250TCP address of some other node in the network. To explain this a bit 249to bind TCP listeners on. The special "address" of C<*> means to bind on
251more detailed we have to look at the topology of an L<AnyEvent::MP> 250every local IP address.
251
252The reason to bind on a TCP port is not just that other nodes can connect
253to us: if no binds are specified, the node will still bind on a dynamic
254port on all local addresses - but in this case we won't know the port, and
255cannot tell other nodes to connect to it as seed node.
256
257A I<seed> is a (fixed) TCP address of some other node in the network. To
258explain the need for seeds we have to look at the topology of a typical
252network. The topology is called a I<fully connected mesh>, here an example 259L<AnyEvent::MP> network. The topology is called a I<fully connected mesh>,
253with 4 nodes: 260here an example with 4 nodes:
254 261
255 N1--N2 262 N1--N2
256 | \/ | 263 | \/ |
257 | /\ | 264 | /\ |
258 N3--N4 265 N3--N4
259 266
260Now imagine another I<node> C<N5>. wants to connect itself to that network: 267Now imagine another node - C<N5> - wants to connect itself to that network:
261 268
262 N1--N2 269 N1--N2
263 | \/ | N5 270 | \/ | N5
264 | /\ | 271 | /\ |
265 N3--N4 272 N3--N4
284 N3--N4--- | 291 N3--N4--- |
285 \________/ 292 \________/
286 293
287All done: C<N5> is now happily connected to the rest of the network. 294All done: C<N5> is now happily connected to the rest of the network.
288 295
289=head3 Setting Up The Profiles 296Of course, this process takes time, during which the node is already
297running. This also means it takes time until the node is fully connected,
298and global groups and other information is available. The best way to deal
299with this is to either retry regularly until you found the resource you
300were looking for, or to only start services on demand after a node has
301become available.
290 302
291Ok, so much to the profile. Now let's setup the C<eg_simple_receiver>
292I<profile> for later use. For the receiver we just give the receiver a
293I<bind>:
294
295 aemp profile eg_simple_receiver setbinds localhost:12266
296
297We use C<localhost> in the example, but in the real world, you usually
298want to use the "real" IP address of your node, so hosts can connect to
299it. Of course, you can specify many binds, and it is also perfectly useful
300to run multiple nodes on the same host. Just keep in mind that other nodes
301will try to I<connect> to those addresses, and this better succeeds if you
302want your network to be in good working conditions.
303
304While we are at it, we setup the I<profile> for the sender in the
305second part of this example, too. We will call the sender I<profile>
306C<eg_simple_sender>. For the sender we set up a I<seed> pointing to the
307receiver:
308
309 aemp profile eg_simple_sender setseeds localhost:12266
310 aemp profile eg_simple_sender setbinds
311
312You might wonder why we setup I<binds> to be empty here: actually, the the
313I<fully> in the I<fully connected mesh> is not the complete truth: If you
314don't configure any I<binds> for a node profile it will parse and try to
315resolve the node ID to find addresses to bind to. In this case we pretend
316that we do not want this and epxlicitly specify an empty binds list, so
317the node will not actually listen on any TCP ports.
318
319Nodes without listeners will not be able to send messages to other nodes
320without listeners, but they can still talk to all other nodes. For this
321example, as well as in many cases in the real world, we can live with this
322restriction, and this makes it easier to avoid DNS (assuming your setup is
323broken, eliminating one potential problem :).
324
325Whee, setting up nodes can be complicated at first, but you only have to
326do it once per network, and you can leave this boring task to the admins
327or end-users that want to use your stuff :)
328
329=head3 Registering The Receiver 303=head3 Registering the Receiver
330 304
331Coming back to our example, we have now introduced the basic purpose of 305Coming back to our example, we have now introduced the basic purpose of
332L<AnyEvent::MP::Global> and C<initialise_node> and its use of profiles. We 306L<AnyEvent::MP::Global> and C<configure> and its use of profiles. We
333also set up our profiles for later use and now we will finally continue 307also set up our profiles for later use and now we will finally continue
334talking about the receiver. 308talking about the receiver.
335 309
336Let's look at the next line(s): 310Let's look at the next line(s):
337 311
338 my $port = port; 312 my $port = port;
339 AnyEvent::MP::Global::register $port, "eg_receivers"; 313 AnyEvent::MP::Global::register $port, "eg_receivers";
340 314
341The C<port> function has already been discussed. It simply creates a new 315The C<port> function has already been discussed. It simply creates a new
342I<port> and returns the I<port ID>. The C<register> function, however, 316I<port> and returns the I<port ID>. The C<register> function, however,
343is new: The first argument is the I<port ID> that we want to add to a 317is new: The first argument is the I<port ID> that we want to add to a
344I<global group>, and its second argument is the name of that I<global 318I<global group>, and its second argument is the name of that I<global
345group>. 319group>.
346 320
347You can choose the name of such a I<global group> freely (prefixing your 321You can choose the name of such a I<global group> freely (prefixing your
348package name is highly recommended!). The purpose of such a group is to 322package name is highly recommended!). The purpose of such a group is to
349store a set of I<port IDs>. This set is made available throughout the 323store a set of I<port IDs>. This set is made available throughout the
350whole L<AnyEvent::MP> network, so that each node can see which ports 324L<AnyEvent::MP> network, so that each node can see which ports belong to
351belong to that group. 325that group.
352 326
353Later we will see how the sender looks for the ports in this I<global 327Later we will see how the sender looks for the ports in this I<global
354group> to send messages to them. 328group> to send messages to them.
355 329
356The last step in the example is to set up a receiver callback for those 330The last step in the example is to set up a receiver callback for those
365 339
366 use AnyEvent; 340 use AnyEvent;
367 use AnyEvent::MP; 341 use AnyEvent::MP;
368 use AnyEvent::MP::Global; 342 use AnyEvent::MP::Global;
369 343
370 initialise_node "eg_simple_sender"; 344 configure nodeid => "eg_sender", seeds => ["*:4040"];
371 345
372 my $find_timer = 346 my $find_timer =
373 AnyEvent->timer (after => 0, interval => 1, cb => sub { 347 AnyEvent->timer (after => 0, interval => 1, cb => sub {
374 my $ports = AnyEvent::MP::Global::find "eg_receivers" 348 my $ports = AnyEvent::MP::Global::find "eg_receivers"
375 or return; 349 or return;
378 for @$ports; 352 for @$ports;
379 }); 353 });
380 354
381 AnyEvent->condvar->recv; 355 AnyEvent->condvar->recv;
382 356
383It's even less code. The C<initialise_node> serves the same purpose as in 357It's even less code. The C<configure> serves the same purpose as in the
384the receiver, we just specify a different profile, the profile we set up 358receiver, but instead of specifying binds we specify a list of seeds -
385without the binds. 359which happens to be the same as the binds used by the receiver, which
360becomes our seed node.
386 361
387Next we set up a timer that repeatedly (every second) calls this chunk of 362Next we set up a timer that repeatedly (every second) calls this chunk of
388code: 363code:
389 364
390 my $ports = AnyEvent::MP::Global::find "eg_receivers" 365 my $ports = AnyEvent::MP::Global::find "eg_receivers"
405the receiver I<port(s)>. 380the receiver I<port(s)>.
406 381
407We then just send a message with a tag and the current time to every 382We then just send a message with a tag and the current time to every
408I<port> in the global group. 383I<port> in the global group.
409 384
410=head3 Multiple Receivers 385=head3 Splitting Network Configuration and Application Code
411 386
412You can even run multiple receivers - the only problem is that they will 387Ok, so far, this works. In the real world, however, the person configuring
413use the same node ID. To avoid this problem, you can either not specify a 388your application to run on a specific network (the end user or network
414profile name at all and rely on DNS and your POSIX node name, or you can 389administrator) is often different to the person coding the application.
415use a special feature called "anonymous nodes":
416 390
417 aemp profile eg_simple_receiver setnodeid anon/ 391Or to put it differently: the arguments passed to configure are usually
392provided not by the programmer, but by whoeever is deplying the program.
418 393
419The special name C<anon/> will be replaced by a random string each time 394To make this easy, AnyEvent::MP supports a simple configuration database,
420the node starts. This way you can start many receivers (they do not bind 395using profiles, which can be managed using the F<aemp> command-line
421on a TCP port, so cnanot collide with each other), and all of them will 396utility.
422receive the central time signal. 397
398When you change both programs above to simply call
399
400 configure;
401
402then AnyEvent::MP tries to look up a profile using the current node name
403in its configuration database, falling back to some global default.
404
405You can run "generic" nodes using the F<aemp> utility as well, and we will
406exploit this in the following way: we configure a profile "seed" and run
407a node using it, whose sole purpose is to be a seed node for our example
408programs.
409
410We bind the seed node to port 4040 on all interfaces:
411
412 aemp profile seed setbinds "*:4040"
413
414And we configure all nodes to use this as seed node (this only works when
415running on the same host, for multiple machines you would provide the IP
416address or hostname of the node running the seed):
417
418 aemp setseeds "*:4040"
419
420Then we run the seed node:
421
422 aemp run profile seed
423
424After that, we can start as many other nodes as we want, and they will all
425use our generic seed node to discover each other.
426
427In fact, starting many receivers nicely illustrates that the time sender
428can have multiple receivers.
423 429
424That's all for now - next time we will teach you about monitoring by 430That's all for now - next time we will teach you about monitoring by
425writing a simple chat client and server :) 431writing a simple chat client and server :)
426 432
427=head1 SEE ALSO 433=head1 SEE ALSO

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines