Articles
Enterprise Architecture
by Nimish Doshi
02/20/2006
In an enterprise, many computers are often either being underutilized due to the nature of the work performed on them or not being used at all because it is after business hours. In many of these institutions, application servers are grinding away taxing CPUs, especially if they are performing CPU-intensive mathematical work, while other machines on the network sit idle. This article proposes a framework for placing Java Messaging Service (JMS) clients on these underutilized machines to offload the work normally performed on a server. The client can listen on a request queue for a unit of work to perform, and respond on a reply queue. In addition, the article presents a BEA WebLogic Integration 8.1 architecture example that reliably distributes units of work to JMS request queues using a workflow with associated Java controls as an alternative framework to distributing work to remote clients.
This article proposes a J2EE framework for addressing the challenge of distributing work to underutilized computer resources. In particular, JMS clients can be placed on these underutilized machines to offload the work normally being performed on a server. The client can listen on a request queue for a unit of work to perform, and respond on a reply queue. A set of message-driven beans can pick up the response messages on the reply queue for further processing. Furthermore, you can use a servlet implementation to administratively start the whole sub-process for creating the units of work to be sent to JMS clients, and also use it to terminate the same sub-process.
I use an ordinary BEA WebLogic Server for one example to distribute discrete units of work to distributed JMS clients. In another more sophisticated example, a BEA WebLogic Integration (WLI) workflow performs similar distribution tasks in a manner that allows for greater elegance in terms of flexibility, reuse of Java controls, and scalability through monitoring of request queues.
In the industry, quite a few examples demonstrate how you can use a JMS framework to exploit underused computers for parallel processing.
With the last example in mind, I'll build a simple example that performs matrix multiplication to illustrate how you can use a JMS framework to offload computing to the computer resources of an enterprise. The JMS client will receive a unit of work instance, after which it will call its
doWork() method. In this simple example, the
doWork() method will multiply two 3x3 matrices and store the results in a results matrix.
The JMS client will then respond to a reply queue with a copy of the unit of work instance that had the work performed on it. A message-driven bean will accept the completed work. Figure 1 shows the various components I'll discuss:
Figure 1. Components in this plain WebLogic Server implementation
This approach makes regular use of the JMS system. In the following sections I'll look at some code, and consider several scaling issues.
Each class placed on the JMS request queue will implement a
UnitOfWork interface that has one method of particular interest,
doWork():
public interface UnitOfWork extends java.io.Serializable {
// This method executes itself on the client machine
public void doWork();
// This method prints the current contents of performed work
public void print();
// This method stores the instance into a backing store
public void store();
}
In our concise, albeit illustrative, example, I have a class called
SimpleMatrix that implements the
UnitOfWork interface:
public class SimpleMatrix implements UnitOfWork {
private Integer m1[][];
private Integer m2[][];
private Integer result[][];
private Integer rows = new Integer(3);
private Integer cols = new Integer(3);
// May initialize m1 and m2 by locating records from a database
public SimpleMatrix() {
}
// This method actually multiplies m1 x m2 and stores in result
public void doWork() {
}
// This method stores result into a backing store
public void store() {
}
// This method prints the current contents of result
public void print() {
}
}
The implementation of the methods is rather self-evident and, for the sake of brevity, will not be described here. See the accompanying code example for a full implementation. The point here is that this
SimpleMatrix instance is passed to a JMS client, which will simply call
doWork() to utilize its CPU to perform the work. For this example I won't actually retrieve or store matrices into a database, but that is what would be expected in a real scenario.