PageBox for Java: Web application deployment using Java PageBox

for
 PageBox for Java 
 API 
 Demo 
 Background 
Presentation User guide Token API Active naming Extensions Implementation Token implementation

Active Naming user guide

Objective

This document explains how to use the Active Naming methods of the PageBox API to allow:

  1. A Web application instance acting as a server to declare entry points to which other Web application instances can forward requests

  2. A Web application instance acting as a client to balance requests between a number of Web application server instances

Audience

Archive developers.

Principle

The principle of Active Naming and its applications are exposed in an Active Naming presentation. Servers declare entry points and clients ask for the most appropriate implementation of these entry points. An entry point has a logical name and three pieces of information:

  • An URL

  • A imperative matching object, the "must"

  • A nice-if-match object, the "niceif"

The "must" object must implement the Serializable interface. The Active Naming implementation uses the equals method to decide if a service instance "must" matches the "must" object provided by the client.

The "niceif" object must implement an ActiveComparable interface defined like this:

interface ActiveComparable extends Serializable {

int compareTo(Object o, ResourceUsage usage);

}

Where o is a niceif object and usage is an object of ResourceUsage class that describes the resource usage on the PageBox hosting the service. This class is defined like this:

class ResourceUsage extends MemUsage {

float perUse;

float perIdle;

float perSystem;

float perUser;

}

MemUsage is defined like this:

class MemUsage implements Serializable {

long free;

long total;

long max;

long netTime;

String msg;

}

Where:

  • perUse is the percentage of CPU used

  • perIdle is the percentage of CPU in idle mode = 100 – peruse

  • perSystem is the percentage of CPU used in system mode

  • perUser is the percentage of CPU used in user mode

  • free is the amount of free memory in bytes. The default implementation uses RunTime.freeMemory and returns the amount of free memory in the Java Virtual Machine.

  • total is the total amount of memory in bytes. The default implementation uses RunTime.totalMemory and returns the total amount of memory in the Java Virtual Machine.

  • max is the maximum amount of memory that can be used in bytes. The default implementation uses RunTime.maxMemory and returns the maximum amount of memory that the Java virtual machine will attempt to use.

  • netTime is the network service time in millisecond. The default implementation uses the time to send a frame to the next station on the ring (token API).

  • msg is null when there were no problems in measurement collection. msg may contain a diagnosis in case of error or "first measure". In the later case CPU data are not valid.

The Active Naming implementation uses the compareTo method to mesure the distance between the "niceif" object provided by the client and the "niceif" objects of the service instances whose "must" objects were found equal. Then the Active Naming implementation randomly chooses a service instance in a list where

  • The service instances whose entry point was declared with a null "niceif" object are listed one time

  • The farest service instances are listed two times

  • The closest service instances are represented (maximum distance - minimum distance + 2) times

PageBoxAPI

A Web application acting as a client uses:

  • ActiveNamingLogon

  • ActiveNamingLogoff

  • getEntries

  • getCandidate

A Web application instance acting as a server uses:

  • addEntry

  • removeEntry

  • clearEntries

ActiveNamingLogon

Signature: void ActiveNamingLogon();

A Web application must call ActiveNamingLogon before using the getEntries and getCandidate methods.

A Web application should call ActiveNamingLogon as soon as it is sure that it will act as a client because Active Naming uses the Token API. Therefore after logon it will take up to token-period before getEntries and getCandidate will return valid responses. In doubt logon when you create your PageBox API instance:

PageBoxAPI inst = new PageBoxAPI(workDir);

inst.ActiveNamingLogon();

ActiveNamingLogoff

Signature: void ActiveNamingLogoff();

A Web application should call ActiveNamingLogoff when it won’t use anymore the getEntries and getCandidate methods. The application should call ActiveNamingLogoff at least when it is unloaded. To monitor unloads a Web application can implement the destroy method on a servlet as demonstrated in the Prometheus example.

getEntries

Signature: String[] getEntries();

getEntries returns the logical names of entries declared by Web application instances everywhere on the ring and null when:

  • The Web application has not called ActiveNamingLogon before

  • No Web aplication instance has declared entries

getCandidate

Signature: String getCandidate(String name, Serializable must, ActiveComparable niceif);

getCandidates returns the URL (Web service, page) of the most appropriate service instance given:

  • name: the logical name of the entry point

  • must: the "must" object

  • niceif: the "niceif" object

getCandidate returns null when:

  • The Web application has not called ActiveNamingLogon before

  • No Web aplication instance has declared entries

  • In case of un-serialization error

addEntry

Signature: void addEntry(String name, Serializable must, ActiveComparable niceif, String url);

addEntry declares an entry point with the following parameters:

  • name: the logical name of the entry point

  • must: the "must" object

  • niceif: the "niceif" object

  • url: URL of the service instance

To call addEntry a Web application doesn’t need to call ActiveNamingLogon. Active Naming automatically registers to the ring when needed. If the Web application calls again addEntry with the same logical name then the entry is updated.

removeEntry

Signature: void removeEntry(String name);

removeEntry removes an entry point identified by its logical name.

If then the Web application has no more entry points and if this Web application didn’t call ActiveNamingLogon the Active Naming un-registers from the ring.

clearEntries

Signature: void clearEntries();

clearEntries removes all entry points declared by the Web application. If the Web application didn’t call ActiveNamingLogon, the Active Naming un-registers from the ring.

Advices

Look at Prometheus for an example of use of Active Naming.

must and niceif semantic

must is about imperative matching. For instance to implement data dependent routing you must use must and not niceif even if you check if a query value is in a range.

niceif is about biased or weighted load balancing. The distance returned by compareTo is used to weight the service instance. Closest a service niceif is to a queried niceif more chances this service instance has to be chosen.

must

The queried and the service musts are compared with the equals method.

Usually equals is commutative: if xxxx.equals(yyyy) is true then yyyy.equals(xxxx) is also true.

Though you can always implement commutative equals this is not required by Active Naming.

The comparison is made with the following code for each service instance:

if (omust == null)

continue;

if (must.equals(omust))

ar.entries.add(ae);

Where must is the queried must and omust is the service must.

If the requestor has a non null must services whose must is null are ignored.

Active Naming always calls the equals method of the queried must.

In the common case where you use Active Naming for data dependent routing with value ranges you can code must in the following way:

class MyMust implements Serializable {

int reqValue;

int srvMin;

int srvMax;

int isReq = -1;

/** Requestor constructor (used in getCandidate) */

MyMust(int myValue) {

reqValue = myValue;

isReq = 1;

}

/** Constructor for service instances (used in addEntry) */

MyMust(int myMin, int myMax) {

srvMin = myMin;

srvMax = myMax;

isReq = 0;

}

MyMust() {}

public boolean equals(Object obj) {

if (!(obj instanceof MyMust))

throw new ClassCastException("Invalid class " + o.getClass().getName());

MyMust oMust = (MyMust)obj;

if (isReq == 0) { // service side - never called by Active Naming

if ((oMust.isReq == 1) && (oMust.reqValue >= srvMin) &&

(oMust.reqValue < srvMax))

return true;

return false;

} else

if (isReq == 1) {

if ((oMust.isReq == 0) && (reqValue >= oMust.srvMin) &&

(reqValue < oMust.srvMax))

return true;

}

return false;

}

}

This implementation is commutative and use a single object – though with two different constructors.

For more complex implementations you can use two different objects, one for the declaration of service instances and one for queries.

niceif

The queried and the service niceifs are compared with the compareTo method.

compareTo returns an signed integer. Active Naming ignores the sign because it measures a distance.

In your implementation avoid large numbers. In many cases a compareTo that returns 0 or 1 is enough.

The comparison is made with the following code for each service instance:

ae.distance = niceif.compareTo(oniceif, me.ru);

if (ae.distance < 0)

ae.distance = - ae.distance;

Where niceif is the queried must, oniceif is the service niceif and me.ru is the ResourceUsage object of the PageBox hosting the service or null if the hosting PageBox failed to collect data.

Active Naming always calls the compareTo method of the queried niceif.

The compareTo method should check the validity of the ResourceUsage fields. Five fields of ResourceUsage should be set up:

  • perUse

  • perIdle

  • free

  • total

  • netTime

Other fields are set up depending on the Operating System and Java Virtual Machine capabilities.

When a long field is not set up its value is -1. When a float field is not set up its value is Float.NEGATIVE_INFINITY.

Contact:support@pagebox.net
©2002-2004 Alexis Grandemange. Last modified .