… | |
… | |
221 | themselves in the appropriate group, and your web frontends can start to |
221 | themselves in the appropriate group, and your web frontends can start to |
222 | find some database backend. |
222 | find some database backend. |
223 | |
223 | |
224 | =head3 C<initialise_node> And The Network |
224 | =head3 C<initialise_node> And The Network |
225 | |
225 | |
226 | Now, lets have a look at the next new thing, the C<initialise_node>: |
226 | Now, let's have a look at the new function, C<initialise_node>: |
227 | |
227 | |
228 | initialise_node "eg_simple_receiver"; |
228 | initialise_node "eg_simple_receiver"; |
229 | |
229 | |
230 | Before we are able to send messages to other nodes we have to initialise |
230 | Before we are able to send messages to other nodes we have to initialise |
|
|
231 | ourself to become a "distributed node". Initialising a node means naming |
|
|
232 | the node, optionally binding some TCP listeners so that other nodes can |
|
|
233 | contact it and connecting to a predefined set of seed addresses so the |
|
|
234 | node can discover the existing network - and the existing network can |
|
|
235 | discover the node! |
|
|
236 | |
231 | ourself. The first argument, the string C<"eg_simple_receiver">, is called the |
237 | The first argument, the string C<"eg_simple_receiver">, is the so-called |
232 | I<profile> of this node. A profile holds some information about the application |
238 | I<profile> to use: A profile holds some information about the application |
233 | that is going to be a node in an L<AnyEvent::MP> network. |
239 | that is going to be a node in an L<AnyEvent::MP> network. Customarily you |
|
|
240 | don't specify a profile name at all: in this case, AnyEvent::MP will use |
|
|
241 | the POSIX nodename. |
234 | |
242 | |
235 | Most importantly the profile allows you to set the I<node id> that your |
243 | The profile allows you to set the I<node ID> that your application will |
236 | application will use. You can also set I<binds> in the profile, meaning that |
244 | use (the node ID defaults to the profile name if not specified). You can |
237 | you can define TCP ports that the application will listen on for incoming |
245 | also set I<binds> in the profile, meaning that you can define TCP ports |
238 | connections from other nodes of the network. |
246 | that the application will listen on for incoming connections from other |
|
|
247 | nodes of the network. |
239 | |
248 | |
240 | Next you can configure I<seeds> in profile. A I<seed> is just a TCP endpoint |
249 | You should also configure I<seeds> in the profile: A I<seed> is just a |
241 | which tells the application where to find other nodes of it's network. To |
250 | TCP address of some other node in the network. To explain this a bit |
242 | explain this a bit more detailed we have to look at the topology of an |
251 | more detailed we have to look at the topology of an L<AnyEvent::MP> |
243 | L<AnyEvent::MP> network. The topology is called a I<fully connected mesh>, here |
252 | network. The topology is called a I<fully connected mesh>, here an example |
244 | an example with 4 nodes: |
253 | with 4 nodes: |
245 | |
254 | |
246 | N1--N2 |
255 | N1--N2 |
247 | | \/ | |
256 | | \/ | |
248 | | /\ | |
257 | | /\ | |
249 | N3--N4 |
258 | N3--N4 |
… | |
… | |
253 | N1--N2 |
262 | N1--N2 |
254 | | \/ | N5 |
263 | | \/ | N5 |
255 | | /\ | |
264 | | /\ | |
256 | N3--N4 |
265 | N3--N4 |
257 | |
266 | |
258 | The new node needs to know the I<binds> of all of those 4 already connected |
267 | The new node needs to know the I<binds> of all nodes already |
259 | nodes. And exactly this is what the I<seeds> are for. Now lets assume that |
268 | connected. Exactly this is what the I<seeds> are for: Let's assume that |
260 | the new node C<N5> has as I<seed> the TCP endpoint of the node C<N2>. |
269 | the new node (C<N5>) uses the TCP address of the node C<N2> as seed. This |
261 | It then connects to C<N2>: |
270 | cuases it to connect to C<N2>: |
262 | |
271 | |
263 | N1--N2____ |
272 | N1--N2____ |
264 | | \/ | N5 |
273 | | \/ | N5 |
265 | | /\ | |
274 | | /\ | |
266 | N3--N4 |
275 | N3--N4 |
267 | |
276 | |
268 | C<N2> then tells C<N5> the I<binds> of the other nodes it is connected to, |
277 | C<N2> then tells C<N5> about the I<binds> of the other nodes it is |
269 | and C<N5> builds up the rest of the connections: |
278 | connected to, and C<N5> creates the rest of the connections: |
270 | |
279 | |
271 | /--------\ |
280 | /--------\ |
272 | N1--N2____| |
281 | N1--N2____| |
273 | | \/ | N5 |
282 | | \/ | N5 |
274 | | /\ | /| |
283 | | /\ | /| |
275 | N3--N4--- | |
284 | N3--N4--- | |
276 | \________/ |
285 | \________/ |
277 | |
286 | |
278 | Finished. C<N5> is now happily connected to the rest of the network. |
287 | All done: C<N5> is now happily connected to the rest of the network. |
279 | |
288 | |
280 | =head3 Setting Up The Profiles |
289 | =head3 Setting Up The Profiles |
281 | |
290 | |
282 | Ok, so much to the profile. Now lets setup the C<eg_simple_receiver> I<profile> |
291 | Ok, so much to the profile. Now let's setup the C<eg_simple_receiver> |
283 | for later. For the receiver we just give the receiver a I<bind>: |
292 | I<profile> for later use. For the receiver we just give the receiver a |
|
|
293 | I<bind>: |
284 | |
294 | |
285 | aemp profile eg_simple_receiver setbinds localhost:12266 |
295 | aemp profile eg_simple_receiver setbinds localhost:12266 |
286 | |
296 | |
|
|
297 | We use C<localhost> in the example, but in the real world, you usually |
|
|
298 | want to use the "real" IP address of your node, so hosts can connect to |
|
|
299 | it. Of course, you can specify many binds, and it is also perfectly useful |
|
|
300 | to run multiple nodes on the same host. Just keep in mind that other nodes |
|
|
301 | will try to I<connect> to those addresses, and this better succeeds if you |
|
|
302 | want your network to be in good working conditions. |
|
|
303 | |
287 | And while we are at it, just setup the I<profile> for the sender in the second |
304 | While we are at it, we setup the I<profile> for the sender in the |
288 | part of this example too. We will call the sender I<profile> |
305 | second part of this example, too. We will call the sender I<profile> |
289 | C<eg_simple_sender>. For the sender we will just setup a I<seed> to the |
306 | C<eg_simple_sender>. For the sender we set up a I<seed> pointing to the |
290 | receiver: |
307 | receiver: |
291 | |
308 | |
292 | aemp profile eg_simple_sender setseeds localhost:12266 |
309 | aemp profile eg_simple_sender setseeds localhost:12266 |
293 | aemp profile eg_simple_sender setbinds |
310 | aemp profile eg_simple_sender setbinds |
294 | |
311 | |
295 | You might wonder why we setup I<binds> to be empty here. Well, there can be |
312 | You might wonder why we setup I<binds> to be empty here: actually, the the |
296 | exceptions to the I<fully> in the I<fully connected mesh> in L<AnyEvent::MP>. |
313 | I<fully> in the I<fully connected mesh> is not the complete truth: If you |
297 | If you don't configure a I<bind> for a node's profile it won't bind itself |
314 | don't configure any I<binds> for a node profile it will parse and try to |
298 | somewhere. These kinds of I<nodes> will not be able to send messages to other |
315 | resolve the node ID to find addresses to bind to. In this case we pretend |
299 | I<nodes> that also didn't I<bind> them self to some TCP address. For this |
316 | that we do not want this and epxlicitly specify an empty binds list, so |
|
|
317 | the node will not actually listen on any TCP ports. |
|
|
318 | |
|
|
319 | Nodes without listeners will not be able to send messages to other nodes |
|
|
320 | without listeners, but they can still talk to all other nodes. For this |
300 | example, as well as some cases in the real world, we can live with this |
321 | example, as well as in many cases in the real world, we can live with this |
301 | limitation. |
322 | restriction, and this makes it easier to avoid DNS (assuming your setup is |
|
|
323 | broken, eliminating one potential problem :). |
302 | |
324 | |
303 | =head3 Registering The Receiver |
325 | =head3 Registering The Receiver |
304 | |
326 | |
305 | Ok, where were we. We now discussed the basic purpose of L<AnyEvent::MP::Global> |
327 | Ok, where were we. We now discussed the basic purpose of L<AnyEvent::MP::Global> |
306 | and initialise_node with it's relations to profiles. We also setup our profiles |
328 | and initialise_node with it's relations to profiles. We also setup our profiles |