PageBox |
|
|
|
|
|
Presentation | User guide | Token API | Active naming | Extensions | Implementation | Token implementation |
Active Naming user guide
Table of content | |
|
This document explains how to use the Active Naming methods of the PageBox API to allow:
A Web application instance acting as a server to declare entry points to which other Web application instances can forward requests
A Web application instance acting as a client to balance requests between a number of Web application server instances
Archive developers.
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
A Web application acting as a client uses:
ActiveNamingLogon
ActiveNamingLogoff
getEntries
getCandidate
A Web application instance acting as a server uses:
addEntry
removeEntry
clearEntries
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(); |
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.
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
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
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.
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.
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.
Look at Prometheus for an example of use of Active Naming.
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.
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.
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
.