153 lines
12 KiB
XML
153 lines
12 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="send-guarantees">
|
|
<title>Guarantees of sends and commits</title>
|
|
<section>
|
|
<title>Guarantees of Transaction Completion</title>
|
|
<para>When committing or rolling back a transaction with ActiveMQ, the request to commit or
|
|
rollback is sent to the server, and the call will block on the client side until a
|
|
response has been received from the server that the commit or rollback was
|
|
executed.</para>
|
|
<para>When the commit or rollback is received on the server, it will be committed to the
|
|
journal, and depending on the value of the parameter <literal
|
|
>journal-sync-transactional</literal> the server will ensure that the commit or
|
|
rollback is durably persisted to storage before sending the response back to the client.
|
|
If this parameter has the value <literal>false</literal> then commit or rollback may not
|
|
actually get persisted to storage until some time after the response has been sent to
|
|
the client. In event of server failure this may mean the commit or rollback never gets
|
|
persisted to storage. The default value of this parameter is <literal>true</literal> so
|
|
the client can be sure all transaction commits or rollbacks have been persisted to
|
|
storage by the time the call to commit or rollback returns.</para>
|
|
<para>Setting this parameter to <literal>false</literal> can improve performance at the
|
|
expense of some loss of transaction durability.</para>
|
|
<para>This parameter is set in <literal>activemq-configuration.xml</literal></para>
|
|
</section>
|
|
<section id="non-transactional-sends">
|
|
<title>Guarantees of Non Transactional Message Sends</title>
|
|
<para>If you are sending messages to a server using a non transacted session, ActiveMQ can be
|
|
configured to block the call to send until the message has definitely reached the
|
|
server, and a response has been sent back to the client. This can be configured
|
|
individually for durable and non-durable messages, and is determined by the
|
|
following two parameters:</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal>BlockOnDurableSend</literal>. If this is set to <literal
|
|
>true</literal> then all calls to send for durable messages on non
|
|
transacted sessions will block until the message has reached the server, and a
|
|
response has been sent back. The default value is <literal>true</literal>.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><literal>BlockOnNonDurableSend</literal>. If this is set to <literal
|
|
>true</literal> then all calls to send for non-durable messages on non
|
|
transacted sessions will block until the message has reached the server, and a
|
|
response has been sent back. The default value is <literal
|
|
>false</literal>.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>Setting block on sends to <literal>true</literal> can reduce performance since each
|
|
send requires a network round trip before the next send can be performed. This means the
|
|
performance of sending messages will be limited by the network round trip time (RTT) of
|
|
your network, rather than the bandwidth of your network. For better performance we
|
|
recommend either batching many messages sends together in a transaction since with a
|
|
transactional session, only the commit / rollback blocks not every send, or, using
|
|
ActiveMQ's advanced <emphasis>asynchronous send acknowledgements feature</emphasis>
|
|
described in <xref linkend="asynchronous-send-acknowledgements"/>.</para>
|
|
<para>If you are using JMS and you're using the JMS service on the server to load your JMS
|
|
connection factory instances into JNDI then these parameters can be configured in
|
|
<literal>activemq-jms.xml</literal> using the elements <literal
|
|
>block-on-durable-send</literal> and <literal
|
|
>block-on-non-durable-send</literal>. If you're using JMS but not using JNDI then
|
|
you can set these values directly on the <literal>ActiveMQConnectionFactory</literal>
|
|
instance using the appropriate setter methods.</para>
|
|
<para>If you're using core you can set these values directly on the <literal
|
|
>ClientSessionFactory</literal> instance using the appropriate setter
|
|
methods.</para>
|
|
<para>When the server receives a message sent from a non transactional session, and that
|
|
message is durable and the message is routed to at least one durable queue, then the
|
|
server will persist the message in permanent storage. If the journal parameter <literal
|
|
>journal-sync-non-transactional</literal> is set to <literal>true</literal> the
|
|
server will not send a response back to the client until the message has been persisted
|
|
and the server has a guarantee that the data has been persisted to disk. The default
|
|
value for this parameter is <literal>true</literal>.</para>
|
|
</section>
|
|
<section id="send-guarantees.nontrans.acks">
|
|
<title>Guarantees of Non Transactional Acknowledgements</title>
|
|
<para>If you are acknowledging the delivery of a message at the client side using a non
|
|
transacted session, ActiveMQ can be configured to block the call to acknowledge until the
|
|
acknowledge has definitely reached the server, and a response has been sent back to the
|
|
client. This is configured with the parameter <literal>BlockOnAcknowledge</literal>. If
|
|
this is set to <literal>true</literal> then all calls to acknowledge on non transacted
|
|
sessions will block until the acknowledge has reached the server, and a response has
|
|
been sent back. You might want to set this to <literal>true</literal> if you want to
|
|
implement a strict <emphasis>at most once</emphasis> delivery policy. The default value
|
|
is <literal>false</literal></para>
|
|
</section>
|
|
<section id="asynchronous-send-acknowledgements">
|
|
<title>Asynchronous Send Acknowledgements</title>
|
|
<para>If you are using a non transacted session but want a guarantee that every message sent
|
|
to the server has reached it, then, as discussed in <xref
|
|
linkend="non-transactional-sends"/>, you can configure ActiveMQ to block the call to
|
|
send until the server has received the message, persisted it and sent back a response.
|
|
This works well but has a severe performance penalty - each call to send needs to block
|
|
for at least the time of a network round trip (RTT) - the performance of sending is thus
|
|
limited by the latency of the network, <emphasis>not</emphasis> limited by the network
|
|
bandwidth.</para>
|
|
<para>Let's do a little bit of maths to see how severe that is. We'll consider a standard
|
|
1Gib ethernet network with a network round trip between the server and the client of
|
|
0.25 ms.</para>
|
|
<para>With a RTT of 0.25 ms, the client can send <emphasis>at most</emphasis> 1000/ 0.25 =
|
|
4000 messages per second if it blocks on each message send.</para>
|
|
<para>If each message is < 1500 bytes and a standard 1500 bytes MTU size is used on the
|
|
network, then a 1GiB network has a <emphasis>theoretical</emphasis> upper limit of (1024
|
|
* 1024 * 1024 / 8) / 1500 = 89478 messages per second if messages are sent without
|
|
blocking! These figures aren't an exact science but you can clearly see that being
|
|
limited by network RTT can have serious effect on performance.</para>
|
|
<para>To remedy this, ActiveMQ provides an advanced new feature called <emphasis>asynchronous
|
|
send acknowledgements</emphasis>. With this feature, ActiveMQ can be configured to
|
|
send messages without blocking in one direction and asynchronously getting
|
|
acknowledgement from the server that the messages were received in a separate stream. By
|
|
de-coupling the send from the acknowledgement of the send, the system is not limited by
|
|
the network RTT, but is limited by the network bandwidth. Consequently better throughput
|
|
can be achieved than is possible using a blocking approach, while at the same time
|
|
having absolute guarantees that messages have successfully reached the server.</para>
|
|
<para>The window size for send acknowledgements is determined by the confirmation-window-size parameter on
|
|
the connection factory or client session factory. Please see <xref linkend="client-reconnection"/> for more info on this.</para>
|
|
<section>
|
|
<title>Asynchronous Send Acknowledgements</title>
|
|
<para>To use the feature using the core API, you implement the interface <literal
|
|
>org.apache.activemq.api.core.client.SendAcknowledgementHandler</literal> and set a handler
|
|
instance on your <literal>ClientSession</literal>.</para>
|
|
<para>Then, you just send messages as normal using your <literal
|
|
>ClientSession</literal>, and as messages reach the server, the server will send
|
|
back an acknowledgement of the send asynchronously, and some time later you are
|
|
informed at the client side by ActiveMQ calling your handler's <literal
|
|
>sendAcknowledged(ClientMessage message)</literal> method, passing in a
|
|
reference to the message that was sent.</para>
|
|
<para>To enable asynchronous send acknowledgements you must make sure <literal>confirmation-window-size</literal> is set to a positive integer value, e.g. 10MiB</para>
|
|
<para>Please see <xref linkend="asynchronous-send-acknowledgements-example"/> for a full
|
|
working example.</para>
|
|
</section>
|
|
</section>
|
|
</chapter>
|