How to change the invoker default to pooled invoker
First step is to find the invoker type desired (i.e. Pooled Invoker). All the invokers are defined in the jboss-service.xml file under the conf directory or in the invokers-service.xml file under the deploy directory. In this case, find the entry for the PooledInvoker and make any changes for its configuration needed. The name attribute value (i.e jboss:service=invoker,type=pooled) will be needed for the next step.
Next, open the standardjboss.xml file in the conf directory for editing. In this file, there are several <invoker-proxy-bindings> elements defined for each of the EJB container types (i.e. entity, stateless, etc.) Duplicate each of the <invoker-proxy-bindings> for each of the EJB container types that you would like to change and change the <name> element to something that denotes use of the pooled invoker. Then change the <invoker-mbean> value to that of the name defined for the pooled invoker in the jboss-service.xml. For example, the invoker-proxy-binding for entity invoker declaration might look like:
<invoker-proxy-bindings> <invoker-proxy-binding> <name>entity-pooled-invoker</name> <invoker-mbean>jboss:service=invoker,type=pooled</invoker-mbean> <proxy-factory>org.jboss.proxy.ejb.ProxyFactory</proxy-factory> <proxy-factory-config> <client-interceptors> <home> <interceptor>org.jboss.proxy.ejb.HomeInterceptor</interceptor> ...
The last step is to find all the container configurations to be changed to use the new invoker and replace the <invoker-proxy-binding-name> value to that of the corresponding name of the new <invoker-proxy-binding>. For example:
<container-configuration> <container-name>Standard CMP 2.x EntityBean</container-name> <call-logging>false</call-logging> <invoker-proxy-binding-name>entity-pooled-invoker</invoker-proxy-binding-name> <sync-on-commit-only>false</sync-on-commit-only> <insert-after-ejb-post-create>false</insert-after-ejb-post-create> <container-interceptors> ...
How the configuration attributes map to implementation
There are two key attributes for the PooledInvoker in regards to how many threads are used in processing requests. The first is the NumAcceptThreads attribute. The value for this attribute will dictate how many threads are created to listen for incoming requests. Each of these threads will be labeled with PooledInvokerAcceptor<thread number>-<server bind port>. These threads will be the ones that call the accept() method of the server socket (which is a blocking call and will wait there till data is received on the network interface for the server socket). As soon as they server socket gets data, it will return a Socket from its accept() method. The accept thread will then either pull a worker thread from its pool, or create a new worker thread. This worker thread is actually the ServerThread class and is identified by the thread name PooledInvokerThread-<host address>-<id>
The size of the pool containing the ServerThreads is controlled by the MaxPoolSize attribute. Thus, if the accept thread can not get a worker thread from the pool and the pool size has reached the MaxPoolSize value, it will wait for one to become available (instead of creating a new one).
Now that know how the accept thread and the worker thread pool works, some other items to consider when setting up configuration. The first is the actual number of accept threads needed. Since the accept thread does nothing more than get the Socket from the ServerSocket and pass off to the worker thread for processing and return to get the next Socket from the ServerSocket, it utilizes very little CPU since is not doing any of the actual request processing. Therefore, this number should be kept low. The default is 1 and is probably fine to stay that way. There is no need to create more than a few as will just create a backlog of accept threads waiting for worker threads (for more concurrent through put, want to increase the MaxPoolSize).
The other thing to note, is that once a worker thread, ServerThread, has been created and placed in the pool, it is only valid for the life of the socket connection. So once an request is processed on the ServerThread, it will send a ping back over the connect. If it does not receive a ping back before the socket timeout period, it will terminate the connection and remove itself from the worker pool (thus automatically shrinking the pool).