Threading, MDBs, and the Mysterious Power of 16
There was a pretty interesting post to one of our internal mailing lists regarding an issue that a customer was seeing when trying to scale up their application. The application architecture was a fairly common one in which the WebLogic Server was accepting batch type requests via a JMS queue. The requests were then processed by an MDB. The system is backed by a really substantial RAC instance and the team was hoping to see the system processing lots and lots of requests concurrently. The test driver that they created was generating on the order of 100 concurrent requests, yet when they looked at the server they found that at most there were 16 threads being created.
Initially the team assumed that they were somehow being constrained by the number of jdbc connections and tried increasing the number of connections in the pool. They found that this did not get them any increased concurrency. Next they increased the max beans in pool for the MDB, but still this did not help either.
What is happening in this case is that the WebLogic Server MDB container is trying to protect against externally generated asynchronous work overwhelming the server. It helps to consider that such batch requests are frequently long running and may consume considerable resources. As the default for max beans in pool is 1000 it is possible to quickly overwhelm a server with a large number of concurrent requests and monopolize the servers resources.
In response to many such issues the decision was made by the EJB container team to limit the number JMS consumers to 16. This has the effect of constraining the number of concurrent requests that are dispatch to 16. The mechanism that is provided to remove this artificial limit is to configure a separate work manager and associated explicitly with that MDB. In doing so you are telling the container that you are aware of the issue and are taking control of the situation.
The Tuning Message-Driven Beans chapter of the Performance & Tuning book describes MDB concurrency in detail and explains all about this issue and describes lots of options. To get a better understanding of work managers and how they can be used to balance the work load in a server there is an excellent white paper entitled Workload Management in WebLogic Server.
The following example should get you started and can be done completely in the context of the weblogic-ejb-jar.xml.
<?xml version="1.0"?>
<weblogic-ejb-jar xmlns=http://www.bea.com/ns/weblogic/10.0
xmlns:j2ee=http://java.sun.com/xml/ns/j2ee
xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation="http://www.bea.com/ns/weblogic/10.0
http://www.bea.com/ns/weblogic/950/weblogic-ejb-jar.xsd">
...
<weblogic-enterprise-bean>
<ejb-name>SomeMDB</ejb-name>
<message-driven-descriptor>
<destination-jndi-name>jms/SomeQueue</destination-jndi-name>
</message-driven-descriptor>
<jndi-name>SomeMDB</jndi-name>
<dispatch-policy>mdb_workmanager</dispatch-policy>
</weblogic-enterprise-bean>
...
<work-manager>
<name>mdb_workmanager</name>
<max-threads-constraint>
<name>maxthreads_32</name>
<count>32</count>
</max-threads-constraint>
</work-manager>
</weblogic-ejb-jar>
With this work manager configuration in place the server will always make sure that if there are no more than 32 threads dedicated to processing requests to this MDB.
