The migration of an active object can be triggered by the active
object itself, or by an external agent. In both cases a single primitive
will eventually get called to perform the migration. It is the method
migrateTo
accessible from a migratable body (a body
that inherits from MigratableBody
).
In order to ease the use of the migration, we provide 2 sets of
static methods on the ProActive
class. The first set is
aimed at the migration triggered from the active object that wants to
migrate. The methods rely on the fact that the calling thread is the active thread of the active object:
migrateTo(Object o)
: migrate to the same
location as an existing active object
migrateTo(String nodeURL)
: migrate to the
location given by the URL of the node
migrateTo(Node node)
: migrate to the location
of the given node
The second set is aimed at the migration triggered from another agent than the target active object. In this case the external agent must have a reference to the Body of the active object it wants to migrate.
migrateTo(Body body, Object o, boolean
priority)
: migrate to the same location as an existing
active object
migrateTo(Body body, String nodeURL, boolean
priority)
: migrate to the location given by the URL of the
node
migrateTo(Body body, Node node, boolean
priority)
: migrate to the location of the given node
Any active object has the ability to migrate. If it references some passive objects, they will also migrate to the new location. Since we rely on the serialization to send the object on the network, the active object must implement the serializable interface. To migrate, an active object must have a method which contains a call to the migration primitive. This call must be the last one in the method, i.e the method must return immediately after. Here is an example of a method in an active object:
public void moveTo(String t) { try { ProActive.migrateTo(t); } catch (Exception e) { e.printStackTrace(); } }
We don't provide any test to check if the call to migrateTo is the
last one in the method, hence if this rule is not enforced, it can lead to
unexpected behavior. Now to make this object move, you just have to call
its moveTo()
method.
import org.objectweb.proactive.ProActive; public class SimpleAgent implements Serializable { public SimpleAgent() { } public void moveTo(String t) { try { ProActive.migrateTo(t); } catch (Exception e) { e.printStackTrace(); } } public String whereAreYou() { try { return InetAddress.getLocalHost().getHostName(); } catch (Exception e) { return 'Localhost lookup failed'; } } public static void main (String[] args) { if (!(args.length>0)) { System.out.println('Usage: java migration.test.TestSimple hostname/NodeName '); System.exit(-1); } SimpleAgent t = null; try { // create the SimpleAgent in this JVM t = (SimpleAgent) ProActive.newActive('migration.test.SimpleAgent',null); } catch (Exception e) { e.printStackTrace(); } // migrate the SimpleAgent to the location identified by the given node URL // we assume here that the node does already exist t.moveTo(args[0]); System.out.println('The Active Object is now on host ' + t.whereAreYou()); } }
The class SimpleAgent implements Serializable
so
the objects created will be able to migrate. We need to provide an empty
constructor to avoid side effects during the creation of active objects.
This object has two methods, moveTo()
which makes it
migrate to the specified location, and whereAreYou()
which returns the hostname of the new location of the agent.
In the main method, we first need to create an active object, which
is done through the call to newActive()
. Once this is
done, we can call methods on it as on any object. We call its
moveTo
method which will make it migrate to the node
specified as parameter and then we ask it what is its current
location.
The migration of an active object uses the serialization. Unfortunately, not all the objects in the Java language are serializable. We are going to see a simple method to deal with such attributes in the case their value does not need to be saved. For more complex cases, the reader can have a look to the Java RMI specifications.
When a NotSerializable
exception is thrown, the
first step to solve the problem is to identify the variable responsible,
i.e the one which is not serializable... In front of the declaration of
this variable, put the keyword transient
. This
indicates that the value of this variable should not be serialized. After
the first migration, this field will be set to null since it has not been
saved. So we have to rebuild it upon arrival of the active object on its
new location. This can easily be done by providing in the active object
the standard method
private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException;
See the Serializable
interface in the standard
JavaDoc to learn more.
There are two way to communicate with an active object which has migrated :
Forwarders
An active object upon leaving a site leaves behind a special object, a forwarder, which is in charge of forwarding incoming messages to the next destination. As time goes, a chain of forwarders builds between a caller and the mobile object. Any message sent to the latter will go through the chain to reach the agent. There is a virtual path between a caller and a mobile object.
Location Server
Communicating with a mobile object can be done with an explicit reference towards the mobile entity, which requires a mean to get its current location is necessary.
In that case there is a two steps communication: first there should be a search to obtain an up-to-date reference (localization), and then the actual communication. The simplest solution is to have a unique location server which maintains a database of the known position of the agents. When an object wants to communicate with an object which has migrated, it queries the serv er which sends back a new reference. If this is the correct one then the communication takes place, otherwise a new query is issued.
Both techniques have their drawbacks. Two problems arise when using a forwarding scheme, especially if the ambition is scalable mobile agents over WAN. First, the forwarders use resources on a site as long as they have not been garbage collected. Thus if a chain exists between to objects, it will remains even if there is no new communications going by. Second, the longer the chain is, the more likely it will be cut because of a hardware or software failure. As a consequence, while forwarders are more efficient under some conditions, they do not appear to be scalable, nor reliable.
The server on the other hand is a single point of failure and a potential bottleneck. If a server is to help communicating with a higher number of mobile agents, then it might not be able to serve requests quickly enough. Furthermore, in case of a crash, it is not possible to communicate with mobile objects until the server is back. It si possible to avoid most of these issues by having redundant servers with load balancing at the cost of increaing complexity.
Based on these observations and taking into account the variability of the environment, we propose a configurable communication protocol which offers the main benefits from both the forwarder and the server while avoiding their drawbacks. Configurable with discrete and continuous parameters, it can be tailored to the environment to offer both performance and reliability.
We introduce time limited forwarders which remain alive only for a limited period. When their lifetime is over, they can just be removed. First of all, this brings an important advantage: scalability due to absence of the DGC and the systematic reclaim of forwarding resources. But of course, this first principle increases the risks of having the forwarding chain cut since this can now happen during the normal execution of the application without any failure. In such a situation, we will rely on a server which will be considered as an alternative solution. This increases the overall reliability.
It is possible to rely on the forwarder to maintain the location of the agent by having them update the server. When they reach the end of their lifetime, they can send to the server their outgoing reference which could be the adress of the agent or another forwarder. The Updating forwarder parameter can be true or false. If true, the main advantage is that it releases the agent from most of the updates. In order to increase reliability, it is possible to have the agent also update the server on a regular basis. This leads us to the third principle.
Each mobile agent has a nominal Time To Update (TTU) after which it will inform the localization server of its new location. Clearly, there are two differents events that influence when a localization server of its current position :
the number of migrations it has performed since its last update,
the time it has spent on the current node without having updated the server.
This observation leads us to the fourth principle :
The TTu is defined as the first occurence of two potential events since the last update:
maxMigrationNb : the number of migrations,
maxTimeOnSite : the time already spent on the current site.
If we consider that both the agent and the forwarders can send updates to the server, the server must be able to make the difference between messages from the forwarders and from the agent; those are always the most up to date. Also, since we don't have any constraint on the Time To Live (TTL) of the forwarders, it could be that a forwarder at the beginning of a chain dies after on at the end. If this happens and we are not careful when dealing with the requests, the server could erase a more up to date reference with an old one.
To summarize, the adaptable mechanism we propose to localize mobile objects, is parameterized by the following values :
TTL forwarder :
- ttl : time (in milliseconds),
- updatingForwarder : boolean,
TTU agents :
- maxMigrationNb : integer,
- maxTimeOnSite : time (in milliseconds).
As a default, ProActive uses a strategy "Forwarders based". It means that the forwarders have a unlimited lifetime and the agent never updates the location server.
To configure your own strategy, you have to edit the file src/org/objectweb/proactive/core/config/ProActiveConfiguration.xml. The four properties are the following :
proactive.mixedlocation.ttl
the TTL value in milliseconds. Use -1 to indicate that the forwarders have a unlimited lifetime.
proactive.mixedlocation.updatingForwarder
true or false.
proactive.mixedlocation.maxMigrationNb
indicates the number of migrations without updating the server. Use -1 to indicate that the agent never updates the server.
proactive.mixedlocation.maxTimeOnSite
the max time spent on a site before updating the server. You can use -1 to indicate that there is no limited time to spend on a site.
A location server is available in the package org.objectweb.proactive.core.body.migration.MixedLocationServer. It can be launched using scripts/unix/migration/LocationServer. You can indicate on which node it have to be running.
Limitation : there can be only one LocationServer for the migration.
© 2001-2007 INRIA Sophia Antipolis All Rights Reserved