activemq-artemis/docs/user-manual/en/send-guarantees.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 &lt; 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>