In this article I will show you how to implement a distributed version of the CommonJ WorkManager specification using Terracotta for Spring. This article is a variation of an article that I wrote for TheServerSide.com titled Distributed Computing Made Easy, an article that can be found here.
What is CommonJ WorkManager?CommonJ is a BEA and IBM joint specification that provides a standard for executing concurrent tasks in a JEE environment. It for example has support for the Master/Worker pattern in its WorkManager API. From BEA's documentation about the specification:
"The Work Manager provides a simple API for application-server-supported concurrent execution of work items. This enables J2EE-based applications (including Servlets and EJBs) to schedule work items for concurrent execution, which will provide greater throughput and increased response time. After an application submits work items to a Work Manager for concurrent execution, the application can gather the results. The Work Manager provides common "join" operations, such as waiting for any or all work items to complete. The Work Manager for Application Servers specification provides an application-server-supported alternative to using lower-level threading APIs, which are inappropriate for use in managed environments such as Servlets and EJBs, as well as being too difficult to use for most applications."What we are going to do is to first implement a the specification as a regular single node multi-threaded application, based on the Master/Worker pattern. We are also going to use the Spring Framework and implement the Master, Worker and Shared Queue entities as three different Spring beans;
We will then use Terracotta for Spring* to transparently and declaratively, turn this implementation into a multi-node, distributed WorkManager.
MyWorkManager bean implements the CommonJ WorkManager interface which has the API that the user uses to schedule
Work and wait for all
Work to be completed. The
MyWorkManager bean does not have any state, and can therefore be configured as a Prototype in the Spring bean config XML file.
Here is how we could implement the work manager bean:
MyWorkManager bean schedules work by adding work to the
WorkQueue bean, which is a simple wrapper around a
java.util.concurrent.BlockingQueue queue. The
WorkQueue bean is the bean that has state, since it holds the queue with all the pending
Work. We need to have a single instance of this queue that can be available to all workers, and we therefore define it as Singleton in the bean config XML file.
The work queue can be implemented like this:
WorkerFinally, we have the
Worker bean. This bean uses a thread pool to spawn up N number of worker threads that continuously grabs and executes Work from the
WorkQueue. During the processing of the
Work, its status flag is maintained (can be one of either Accepted, Started, Completed or Rejected), this is needed in order for the
MyWorkManager bean to be able to continuously monitor the status of the Work it has scheduled. The
Worker bean does not have any shared state and is configured as a Prototype in the bean config XML file.
This is what a worker bean implementation can look like. As you can see we choose to make use of the
Executor thread pool implementation in the
AssemblyThese three beans can now be wired up by the Spring bean config file: We now have a fully functional local, multi-threaded, implementation of the CommonJ WorkManager specification.
Making the WorkManager distributedNow comes the hard part right? Well...no. It turns out that in order to turn this implementation into a distributed
WorkManager, all we have to do is to create a Terracotta configuration file in which we declare the Spring beans that we want to share across the cluster:
Now we have a fully distributed, multi-JVM CommonJ WorkManager.
Client usageUsing the distributed work manager is now simply a matter of getting the bean from the application context and invoke
To start up a
Worker you simply have to get the
Worker bean from the application context and invoke
The usage of the distributed version would roughly be to start up one
WorkManager bean and N number of
Worker beans, each one on a different JVM.
That is all there is to it. Now we have a simple, distributed, reliable, high-performant and scalable CommonJ WorkManager ready for use.
* RC 1 of Terracotta for Spring was released some days ago (9/12/2006) and is free for production use for up to two nodes.