MIRA
Tutorial: Distributed computing - How to use MIRA across different processes in a network


Prerequisites

This tutorial assumes that you know how to create configuration files and launch a framework using these files via mira, miragui or miracenter.

Introduction

In this tutorial we will learn how to distribute a single application (consisting of several units) across multiple processes or even multiple systems in a network. This means we will split a single configuration file into multiple ones, where each file contains a subset of the units of our application. Each configuration file is then used to launch the contained units in a separate process. All processes (frameworks) will work together using network connections to provide the same functionality as the original application.

The initial configuration

The following code will form the XML configuration file of our application that we like to distribute across multiple processes. Just paste that code into a file and save it as OneProcess.xml in your tutorial or demo folder.

<root>
<unit id="IntPublisher" class="mira::fw::IntPublisherUnit"/>
<unit id="IntSubscriber" class="mira::fw::IntSubscriberUnit"/>
</root>

Our application consists of two units that come with the MIRA installation and can be found in [MIRA ROOT]/framework/examples/fw/IntPublisherSubscriber. One produces a continuously increasing integer value that it writes to a channel called "Int". The other unit is a consumer that just subscribes to that channel and writes its content to the console. This configuration can be launched with the mira tool and debug level >= 3 (via the -d or –debug parameter) and should produce the following output:

> mira path/to/your/file/OneProcess.xml -d3
...
[NOTICE ] 2012-Apr-10 17:10:04.895499 Subscriber got value 0
[NOTICE ] 2012-Apr-10 17:10:05.391253 Subscriber got value 1
[NOTICE ] 2012-Apr-10 17:10:05.891277 Subscriber got value 2
[NOTICE ] 2012-Apr-10 17:10:06.391281 Subscriber got value 3
[NOTICE ] 2012-Apr-10 17:10:06.891229 Subscriber got value 4
[NOTICE ] 2012-Apr-10 17:10:07.391230 Subscriber got value 5
...

Splitting it up

Since our application has only two units, we will split it into two processes. Just create a PublisherProcess.xml file with the following content:

<root>
<unit id="IntPublisher" class="mira::fw::IntPublisherUnit"/>
</root>

and a SubscriberProcess.xml file that looks like:

<root>
<unit id="IntSubscriber" class="mira::fw::IntSubscriberUnit"/>
</root>

Now we have two configuration files - one that launches our publisher unit and one launching our subscriber unit. Each configuration can be started using the mira tool like we have done before. But right now there would be no connection between these, so the subscriber will not receive any data and therefore not print anything.

Putting it back together

In MIRA, we have no single server were each Framework connects to. Instead, each mira tool can act either as a server where other Frameworks connect to and/or a client that connects to other Frameworks. In our case, we need to decide which configuration we launch as a server and which as a client. We will start the Framework that contains the publisher as server and the one that contains the subscriber as client.

To that purpose, we need to change the way we execute mira. For the publisher, we need to specify a port the Framework listens on for incoming connections from other Frameworks. We chose 1234 as port and specify it via the -p or –fw-port parameter:

> mira path/to/your/file/PublisherProcess.xml -p1234

Now the first Framework is started and our publisher is already working. We need to keep this Framework running while opening another console. On the new console we start our second Framework that acts as a client and contains our subscriber. We need to specify the addresses of all the Frameworks we like to connect to. Since we are running on the same system the address is our local host (127.0.0.1) and the port is 1234 as we have defined before. We tell mira about this known Framework via the -k or –known-fw parameter. This parameter takes a comma separated list of all known Frameworks with syntax HOST:PORT (don't forget to set the right debug level)

> mira path/to/your/file/PublisherProcess.xml -k127.0.0.1:1234 -d3
...
[NOTICE ] 2012-Apr-10 17:47:38.329854 Subscriber got value 96
[NOTICE ] 2012-Apr-10 17:47:38.829839 Subscriber got value 97
[NOTICE ] 2012-Apr-10 17:47:39.329826 Subscriber got value 98
[NOTICE ] 2012-Apr-10 17:47:39.829818 Subscriber got value 99
[NOTICE ] 2012-Apr-10 17:47:40.329853 Subscriber got value 100
[NOTICE ] 2012-Apr-10 17:47:40.829848 Subscriber got value 101
[NOTICE ] 2012-Apr-10 17:47:41.329829 Subscriber got value 102
...

Notice that our publisher was already running for a while so it already increased its integer value several times.

When connecting Frameworks that are located on different systems in a network, it may be necessary to allow connections to pass your firewall. This is ONLY needed on the server side, e.g. by opening the firewall for the used ports on the system that runs a Framework that acts as a server.

Adapting the configuration files

To omit typing the port and known framework address each time we start mira, we can store these details in the configuration files. Edit the PublisherProcess.xml file and add a XML configuration node for the communication part of the Framework:

<root>
<communication>
<Port>1234</Port>
</communication>
<unit id="IntPublisher" class="mira::fw::IntPublisherUnit"/>
</root>

Now we can start the publisher without specifying a port each time.

To adapt the subscriber configuration edit the SubscriberProcess.xml file so that it looks like:

<root>
<communication>
<version type="mira::RemoteModule">2</version>
<KnownFrameworks>
<item>
<address>127.0.0.1:1234</address>
</item>
</KnownFrameworks>
</communication>
<unit id="IntSubscriber" class="mira::fw::IntSubscriberUnit"/>
</root>

Now when launching this configuration the framework will try to connect to the given address without the need of the -k or –known-fw parameter.

The port given via command line will overwrite any port specified in the configuration file. Known frameworks given on the command line will be added to the list of known frameworks like the ones specified in the configuration file and will NOT overwrite them.