305 lines
20 KiB
XML
305 lines
20 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="perf-tuning">
|
|
<title>Performance Tuning</title>
|
|
<para>In this chapter we'll discuss how to tune ActiveMQ for optimum performance.</para>
|
|
<section>
|
|
<title>Tuning persistence</title>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Put the message journal on its own physical volume. If the disk is shared with
|
|
other processes e.g. transaction co-ordinator, database or other journals which
|
|
are also reading and writing from it, then this may greatly reduce performance
|
|
since the disk head may be skipping all over the place between the different
|
|
files. One of the advantages of an append only journal is that disk head
|
|
movement is minimised - this advantage is destroyed if the disk is shared. If
|
|
you're using paging or large messages make sure they're ideally put on separate
|
|
volumes too.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Minimum number of journal files. Set <literal>journal-min-files</literal> to a
|
|
number of files that would fit your average sustainable rate. If you see new
|
|
files being created on the journal data directory too often, i.e. lots of data
|
|
is being persisted, you need to increase the minimal number of files, this way
|
|
the journal would reuse more files instead of creating new data files.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Journal file size. The journal file size should be aligned to the capacity of
|
|
a cylinder on the disk. The default value 10MiB should be enough on most
|
|
systems.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Use AIO journal. If using Linux, try to keep your journal type as AIO. AIO
|
|
will scale better than Java NIO.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Tune <literal>journal-buffer-timeout</literal>. The timeout can be increased
|
|
to increase throughput at the expense of latency.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>If you're running AIO you might be able to get some better performance by
|
|
increasing <literal>journal-max-io</literal>. DO NOT change this parameter if
|
|
you are running NIO.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
<section>
|
|
<title>Tuning JMS</title>
|
|
<para>There are a few areas where some tweaks can be done if you are using the JMS
|
|
API</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Disable message id. Use the <literal>setDisableMessageID()</literal> method on
|
|
the <literal>MessageProducer</literal> class to disable message ids if you don't
|
|
need them. This decreases the size of the message and also avoids the overhead
|
|
of creating a unique ID.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Disable message timestamp. Use the <literal
|
|
>setDisableMessageTimeStamp()</literal> method on the <literal
|
|
>MessageProducer</literal> class to disable message timestamps if you don't
|
|
need them.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Avoid <literal>ObjectMessage</literal>. <literal>ObjectMessage</literal> is
|
|
convenient but it comes at a cost. The body of a <literal
|
|
>ObjectMessage</literal> uses Java serialization to serialize it to bytes.
|
|
The Java serialized form of even small objects is very verbose so takes up a lot
|
|
of space on the wire, also Java serialization is slow compared to custom
|
|
marshalling techniques. Only use <literal>ObjectMessage</literal> if you really
|
|
can't use one of the other message types, i.e. if you really don't know the type
|
|
of the payload until run-time.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Avoid <literal>AUTO_ACKNOWLEDGE</literal>. <literal>AUTO_ACKNOWLEDGE</literal>
|
|
mode requires an acknowledgement to be sent from the server for each message
|
|
received on the client, this means more traffic on the network. If you can, use
|
|
<literal>DUPS_OK_ACKNOWLEDGE</literal> or use <literal
|
|
>CLIENT_ACKNOWLEDGE</literal> or a transacted session and batch up many
|
|
acknowledgements with one acknowledge/commit. </para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Avoid durable messages. By default JMS messages are durable. If you don't
|
|
really need durable messages then set them to be non-durable. Durable messages
|
|
incur a lot more overhead in persisting them to storage.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Batch many sends or acknowledgements in a single transaction. ActiveMQ will
|
|
only require a network round trip on the commit, not on every send or
|
|
acknowledgement.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
<section>
|
|
<title>Other Tunings</title>
|
|
<para>There are various other places in ActiveMQ where we can perform some tuning:</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Use Asynchronous Send Acknowledgements. If you need to send durable messages
|
|
non transactionally and you need a guarantee that they have reached the server
|
|
by the time the call to send() returns, don't set durable messages to be sent
|
|
blocking, instead use asynchronous send acknowledgements to get your
|
|
acknowledgements of send back in a separate stream, see <xref
|
|
linkend="send-guarantees"/> for more information on this.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Use pre-acknowledge mode. With pre-acknowledge mode, messages are acknowledged
|
|
<literal>before</literal> they are sent to the client. This reduces the
|
|
amount of acknowledgement traffic on the wire. For more information on this, see
|
|
<xref linkend="pre-acknowledge"/>.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Disable security. You may get a small performance boost by disabling security
|
|
by setting the <literal>security-enabled</literal> parameter to <literal
|
|
>false</literal> in <literal>activemq-configuration.xml</literal>.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Disable persistence. If you don't need message persistence, turn it off
|
|
altogether by setting <literal>persistence-enabled</literal> to false in
|
|
<literal>activemq-configuration.xml</literal>.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Sync transactions lazily. Setting <literal
|
|
>journal-sync-transactional</literal> to <literal>false</literal> in
|
|
<literal>activemq-configuration.xml</literal> can give you better
|
|
transactional persistent performance at the expense of some possibility of loss
|
|
of transactions on failure. See <xref linkend="send-guarantees"/> for more
|
|
information.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Sync non transactional lazily. Setting <literal
|
|
>journal-sync-non-transactional</literal> to <literal>false</literal> in
|
|
<literal>activemq-configuration.xml</literal> can give you better
|
|
non-transactional persistent performance at the expense of some possibility of
|
|
loss of durable messages on failure. See <xref linkend="send-guarantees"/> for
|
|
more information.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Send messages non blocking. Setting <literal>block-on-durable-send</literal>
|
|
and <literal>block-on-non-durable-send</literal> to <literal>false</literal> in
|
|
<literal>activemq-jms.xml</literal> (if you're using JMS and JNDI) or
|
|
directly on the ServerLocator. This means you don't have to wait a whole
|
|
network round trip for every message sent. See <xref linkend="send-guarantees"/>
|
|
for more information.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>If you have very fast consumers, you can increase consumer-window-size. This
|
|
effectively disables consumer flow control.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Socket NIO vs Socket Old IO. By default ActiveMQ uses old (blocking) on the
|
|
server and the client side (see the chapter on configuring transports for more
|
|
information <xref linkend="configuring-transports"/>). NIO is much more scalable
|
|
but can give you some latency hit compared to old blocking IO. If you need to be
|
|
able to service many thousands of connections on the server, then you should
|
|
make sure you're using NIO on the server. However, if don't expect many
|
|
thousands of connections on the server you can keep the server acceptors using
|
|
old IO, and might get a small performance advantage.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Use the core API not JMS. Using the JMS API you will have slightly lower
|
|
performance than using the core API, since all JMS operations need to be
|
|
translated into core operations before the server can handle them. If using the
|
|
core API try to use methods that take <literal>SimpleString</literal> as much as
|
|
possible. <literal>SimpleString</literal>, unlike java.lang.String does not
|
|
require copying before it is written to the wire, so if you re-use <literal
|
|
>SimpleString</literal> instances between calls then you can avoid some
|
|
unnecessary copying.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
<section>
|
|
<title>Tuning Transport Settings</title>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>TCP buffer sizes. If you have a fast network and fast machines you may get a
|
|
performance boost by increasing the TCP send and receive buffer sizes. See the
|
|
<xref linkend="configuring-transports"/> for more information on this. </para>
|
|
<note>
|
|
<para> Note that some operating systems like later versions of Linux include TCP
|
|
auto-tuning and setting TCP buffer sizes manually can prevent auto-tune from
|
|
working and actually give you worse performance!</para>
|
|
</note>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Increase limit on file handles on the server. If you expect a lot of
|
|
concurrent connections on your servers, or if clients are rapidly opening and
|
|
closing connections, you should make sure the user running the server has
|
|
permission to create sufficient file handles.</para>
|
|
<para>This varies from operating system to operating system. On Linux systems you
|
|
can increase the number of allowable open file handles in the file <literal
|
|
>/etc/security/limits.conf</literal> e.g. add the lines
|
|
<programlisting>
|
|
serveruser soft nofile 20000
|
|
serveruser hard nofile 20000</programlisting>
|
|
This would allow up to 20000 file handles to be open by the user <literal
|
|
>serveruser</literal>. </para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Use <literal>batch-delay</literal> and set <literal>direct-deliver</literal>
|
|
to false for the best throughput for very small messages. ActiveMQ comes with a
|
|
preconfigured connector/acceptor pair (<literal>netty-throughput</literal>) in
|
|
<literal>activemq-configuration.xml</literal> and JMS connection factory
|
|
(<literal>ThroughputConnectionFactory</literal>) in <literal
|
|
>activemq-jms.xml</literal>which can be used to give the very best
|
|
throughput, especially for small messages. See the <xref
|
|
linkend="configuring-transports"/> for more information on this.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
<section>
|
|
<title>Tuning the VM</title>
|
|
<para>We highly recommend you use the latest Java JVM for the best performance. We test
|
|
internally using the Sun JVM, so some of these tunings won't apply to JDKs from other
|
|
providers (e.g. IBM or JRockit)</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Garbage collection. For smooth server operation we recommend using a parallel
|
|
garbage collection algorithm, e.g. using the JVM argument <literal
|
|
>-XX:+UseParallelOldGC</literal> on Sun JDKs.</para>
|
|
</listitem>
|
|
<listitem id="perf-tuning.memory">
|
|
<para>Memory settings. Give as much memory as you can to the server. ActiveMQ can run
|
|
in low memory by using paging (described in <xref linkend="paging"/>) but if it
|
|
can run with all queues in RAM this will improve performance. The amount of
|
|
memory you require will depend on the size and number of your queues and the
|
|
size and number of your messages. Use the JVM arguments <literal>-Xms</literal>
|
|
and <literal>-Xmx</literal> to set server available RAM. We recommend setting
|
|
them to the same high value.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Aggressive options. Different JVMs provide different sets of JVM tuning
|
|
parameters, for the Sun Hotspot JVM the full list of options is available <ulink
|
|
url="http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html"
|
|
>here</ulink>. We recommend at least using <literal
|
|
>-XX:+AggressiveOpts</literal> and<literal>
|
|
-XX:+UseFastAccessorMethods</literal>. You may get some mileage with the
|
|
other tuning parameters depending on your OS platform and application usage
|
|
patterns.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
<section>
|
|
<title>Avoiding Anti-Patterns</title>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Re-use connections / sessions / consumers / producers. Probably the most
|
|
common messaging anti-pattern we see is users who create a new
|
|
connection/session/producer for every message they send or every message they
|
|
consume. This is a poor use of resources. These objects take time to create and
|
|
may involve several network round trips. Always re-use them.</para>
|
|
<note>
|
|
<para>Some popular libraries such as the Spring JMS Template are known to use
|
|
these anti-patterns. If you're using Spring JMS Template and you're getting
|
|
poor performance you know why. Don't blame ActiveMQ! The Spring JMS Template
|
|
can only safely be used in an app server which caches JMS sessions (e.g.
|
|
using JCA), and only then for sending messages. It cannot be safely be used
|
|
for synchronously consuming messages, even in an app server. </para>
|
|
</note>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Avoid fat messages. Verbose formats such as XML take up a lot of space on the
|
|
wire and performance will suffer as result. Avoid XML in message bodies if you
|
|
can.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Don't create temporary queues for each request. This common anti-pattern
|
|
involves the temporary queue request-response pattern. With the temporary queue
|
|
request-response pattern a message is sent to a target and a reply-to header is
|
|
set with the address of a local temporary queue. When the recipient receives the
|
|
message they process it then send back a response to the address specified in
|
|
the reply-to. A common mistake made with this pattern is to create a new
|
|
temporary queue on each message sent. This will drastically reduce performance.
|
|
Instead the temporary queue should be re-used for many requests.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Don't use Message-Driven Beans for the sake of it. As soon as you start using
|
|
MDBs you are greatly increasing the codepath for each message received compared
|
|
to a straightforward message consumer, since a lot of extra application server
|
|
code is executed. Ask yourself do you really need MDBs? Can you accomplish the
|
|
same task using just a normal message consumer?</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
</chapter>
|