157 lines
11 KiB
XML
157 lines
11 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!-- ============================================================================= -->
|
|
<!-- Licensed to the Apache Software Foundation (ASF) under one or more -->
|
|
<!-- contributor license agreements. See the NOTICE file distributed with -->
|
|
<!-- this work for additional information regarding copyright ownership. -->
|
|
<!-- The ASF licenses this file to You under the Apache License, Version 2.0 -->
|
|
<!-- (the "License"); you may not use this file except in compliance with -->
|
|
<!-- the License. You may obtain a copy of the License at -->
|
|
<!-- -->
|
|
<!-- http://www.apache.org/licenses/LICENSE-2.0 -->
|
|
<!-- -->
|
|
<!-- Unless required by applicable law or agreed to in writing, software -->
|
|
<!-- distributed under the License is distributed on an "AS IS" BASIS, -->
|
|
<!-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
|
|
<!-- See the License for the specific language governing permissions and -->
|
|
<!-- limitations under the License. -->
|
|
<!-- ============================================================================= -->
|
|
|
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
<!ENTITY % BOOK_ENTITIES SYSTEM "ActiveMQ_User_Manual.ent">
|
|
%BOOK_ENTITIES;
|
|
]>
|
|
<chapter id="thread-pooling">
|
|
<title>Thread management</title>
|
|
<para>This chapter describes how ActiveMQ uses and pools threads and how you can manage
|
|
them.</para>
|
|
<para>First we'll discuss how threads are managed and used on the server side, then we'll look
|
|
at the client side.</para>
|
|
<section>
|
|
<title>Server-Side Thread Management</title>
|
|
<para>Each ActiveMQ Server maintains a single thread pool for general use, and a scheduled
|
|
thread pool for scheduled use. A Java scheduled thread pool cannot be configured to use
|
|
a standard thread pool, otherwise we could use a single thread pool for both scheduled
|
|
and non scheduled activity.</para>
|
|
<para>A separate thread pool is also used to service connections. ActiveMQ can use "old"
|
|
(blocking) IO or "new" (non-blocking) IO also called NIO. Both of these options use
|
|
a separate thread pool, but each of them behaves uniquely.</para>
|
|
<para>Since old IO requires a thread per connection its thread pool is unbounded. The thread
|
|
pool is created via <literal>
|
|
java.util.concurrent.Executors.newCachedThreadPool(ThreadFactory)</literal>. As the
|
|
JavaDoc for this method states:
|
|
<quote>Creates a thread pool that creates new threads as needed, but will reuse previously
|
|
constructed threads when they are available, and uses the provided ThreadFactory to create
|
|
new threads when needed.</quote>
|
|
Threads from this pool which are idle for more than 60 seconds will time out and be
|
|
removed. If old IO connections were serviced from the standard pool the pool would
|
|
easily get exhausted if too many connections were made, resulting in the server "hanging"
|
|
since it has no remaining threads to do anything else. However, even an unbounded thread
|
|
pool can run into trouble if it becomes too large. If you require the server to handle
|
|
many concurrent connections you should use NIO, not old IO.</para>
|
|
<para>When using new IO (NIO), ActiveMQ will, by default, cap its thread pool at three times
|
|
the number of cores (or hyper-threads) as reported by <literal>
|
|
Runtime.getRuntime().availableProcessors()</literal> for processing incoming packets.
|
|
To override this value, you can set the number of threads by specifying the parameter
|
|
<literal>nio-remoting-threads</literal> in the transport configuration. See the
|
|
<xref linkend="configuring-transports"/> for more information on this.</para>
|
|
<para>There are also a small number of other places where threads are used directly, we'll
|
|
discuss each in turn.</para>
|
|
<section id="server.scheduled.thread.pool">
|
|
<title>Server Scheduled Thread Pool</title>
|
|
<para>The server scheduled thread pool is used for most activities on the server side
|
|
that require running periodically or with delays. It maps internally to a <literal
|
|
>java.util.concurrent.ScheduledThreadPoolExecutor</literal> instance.</para>
|
|
<para>The maximum number of thread used by this pool is configure in <literal
|
|
>activemq-configuration.xml</literal> with the <literal
|
|
>scheduled-thread-pool-max-size</literal> parameter. The default value is
|
|
<literal>5</literal> threads. A small number of threads is usually sufficient
|
|
for this pool.</para>
|
|
</section>
|
|
<section>
|
|
<title>General Purpose Server Thread Pool</title>
|
|
<para>This general purpose thread pool is used for most asynchronous actions on the
|
|
server side. It maps internally to a <literal
|
|
>java.util.concurrent.ThreadPoolExecutor</literal> instance.</para>
|
|
<para>The maximum number of thread used by this pool is configure in <literal
|
|
>activemq-configuration.xml</literal> with the <literal
|
|
>thread-pool-max-size</literal> parameter.</para>
|
|
<para>If a value of <literal>-1</literal> is used this signifies that the thread pool
|
|
has no upper bound and new threads will be created on demand if there are not enough
|
|
threads available to satisfy a request. If activity later subsides then threads are
|
|
timed-out and closed.</para>
|
|
<para>If a value of <literal>n</literal> where <literal>n</literal>is a positive integer
|
|
greater than zero is used this signifies that the thread pool is bounded. If more
|
|
requests come in and there are no free threads in the pool and the pool is full then
|
|
requests will block until a thread becomes available. It is recommended that a
|
|
bounded thread pool is used with caution since it can lead to dead-lock situations
|
|
if the upper bound is chosen to be too low.</para>
|
|
<para>The default value for <literal>thread-pool-max-size</literal> is <literal
|
|
>30</literal>.</para>
|
|
<para>See the <ulink
|
|
url="http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.htm"
|
|
>J2SE javadoc</ulink> for more information on unbounded (cached), and bounded
|
|
(fixed) thread pools.</para>
|
|
</section>
|
|
<section>
|
|
<title>Expiry Reaper Thread</title>
|
|
<para>A single thread is also used on the server side to scan for expired messages in
|
|
queues. We cannot use either of the thread pools for this since this thread needs to
|
|
run at its own configurable priority.</para>
|
|
<para>For more information on configuring the reaper, please see <xref
|
|
linkend="message-expiry"/>.</para>
|
|
</section>
|
|
<section>
|
|
<title>Asynchronous IO</title>
|
|
<para>Asynchronous IO has a thread pool for receiving and dispatching events out of the
|
|
native layer. You will find it on a thread dump with the prefix
|
|
ActiveMQ-AIO-poller-pool. ActiveMQ uses one thread per opened file on the journal
|
|
(there is usually one).</para>
|
|
<para>There is also a single thread used to invoke writes on libaio. We do that to avoid
|
|
context switching on libaio that would cause performance issues. You will find this
|
|
thread on a thread dump with the prefix ActiveMQ-AIO-writer-pool.</para>
|
|
</section>
|
|
</section>
|
|
<section id="thread-pooling.client.side">
|
|
<title>Client-Side Thread Management</title>
|
|
<para>On the client side, ActiveMQ maintains a single static scheduled thread pool and a
|
|
single static general thread pool for use by all clients using the same classloader in
|
|
that JVM instance.</para>
|
|
<para>The static scheduled thread pool has a maximum size of <literal>5</literal> threads,
|
|
and the general purpose thread pool has an unbounded maximum size.</para>
|
|
<para>If required ActiveMQ can also be configured so that each <literal
|
|
>ClientSessionFactory</literal> instance does not use these static pools but instead
|
|
maintains its own scheduled and general purpose pool. Any sessions created from that
|
|
<literal>ClientSessionFactory</literal> will use those pools instead.</para>
|
|
<para>To configure a <literal>ClientSessionFactory</literal> instance to use its own pools,
|
|
simply use the appropriate setter methods immediately after creation, for
|
|
example:</para>
|
|
<programlisting>
|
|
ServerLocator locator = ActiveMQClient.createServerLocatorWithoutHA(...)
|
|
ClientSessionFactory myFactory = locator.createClientSessionFactory();
|
|
myFactory.setUseGlobalPools(false);
|
|
myFactory.setScheduledThreadPoolMaxSize(10);
|
|
myFactory.setThreadPoolMaxSize(-1); </programlisting>
|
|
<para>If you're using the JMS API, you can set the same parameters on the
|
|
ClientSessionFactory and use it to create the <literal>ConnectionFactory</literal>
|
|
instance, for example:</para>
|
|
<programlisting>
|
|
ConnectionFactory myConnectionFactory = ActiveMQJMSClient.createConnectionFactory(myFactory);</programlisting>
|
|
<para>If you're using JNDI to instantiate <literal>ActiveMQConnectionFactory</literal>
|
|
instances, you can also set these parameters in the <literal>activemq-jms.xml</literal>
|
|
file where you describe your connection factory, for example:</para>
|
|
<programlisting>
|
|
<connection-factory name="ConnectionFactory">
|
|
<connectors>
|
|
<connector-ref connector-name="netty"/>
|
|
</connectors>
|
|
<entries>
|
|
<entry name="ConnectionFactory"/>
|
|
<entry name="XAConnectionFactory"/>
|
|
</entries>
|
|
<use-global-pools>false</use-global-pools>
|
|
<scheduled-thread-pool-max-size>10</scheduled-thread-pool-max-size>
|
|
<thread-pool-max-size>-1</thread-pool-max-size>
|
|
</connection-factory></programlisting>
|
|
</section>
|
|
</chapter>
|