2014-10-31 06:20:28 -04:00
|
|
|
<html>
|
|
|
|
<head>
|
2014-11-19 03:44:57 -05:00
|
|
|
<title>ActiveMQ No Consumer Buffering Example</title>
|
2014-10-31 06:20:28 -04:00
|
|
|
<link rel="stylesheet" type="text/css" href="../common/common.css" />
|
|
|
|
<link rel="stylesheet" type="text/css" href="../common/prettify.css" />
|
|
|
|
<script type="text/javascript" src="../common/prettify.js"></script>
|
|
|
|
</head>
|
|
|
|
<body onload="prettyPrint()">
|
|
|
|
<h1>No Consumer Buffering Example</h1>
|
|
|
|
|
2014-11-19 03:44:57 -05:00
|
|
|
<p>By default, ActiveMQ consumers buffer messages from the server in a client side buffer
|
2014-10-31 06:20:28 -04:00
|
|
|
before actual delivery actually occurs.</p>
|
|
|
|
<p>This improves performance since otherwise every time you called receive() or had processed the last
|
2014-11-19 03:44:57 -05:00
|
|
|
message in a MessageListener onMessage() method, the ActiveMQ client would have to go the
|
2014-10-31 06:20:28 -04:00
|
|
|
server to request the next message involving a network round trip for every message reducing performance.</p>
|
2014-11-19 03:44:57 -05:00
|
|
|
<p>Therefore, by default, ActiveMQ pre-fetches messages into a buffer on each consumer. The total maximum size of
|
2014-10-31 06:20:28 -04:00
|
|
|
messages in bytes that will be buffered on each consumer is determined by the <code>consumer-window-size</code>
|
|
|
|
parameter on the connection factory.</p>
|
|
|
|
<p>In some cases it is not desirable to buffer any messages on the client side consumer.</p>
|
|
|
|
<p>An example would be an order queue which had multiple consumers that processed orders from the queue.
|
|
|
|
Each order takes a significant time to process, but each one should be processed in a timely fashion.</p>
|
|
|
|
<p>If orders were buffered in each consumer, and a new consumer was added that consumer would not be able
|
|
|
|
to process orders which were already in the client side buffer of another consumer.</p>
|
|
|
|
<p>To turn off client side buffering of messages, set <code>consumer-window-size</code> to zero.</p>
|
|
|
|
|
2014-11-19 03:44:57 -05:00
|
|
|
<p>With ActiveMQ you can specify a maximum consume rate at which a JMS MessageConsumer will consume messages.
|
2014-11-19 14:58:44 -05:00
|
|
|
This can be specified when creating or deploying the connection factory. See <code>activemq-jms.xml</code></p>
|
2014-10-31 06:20:28 -04:00
|
|
|
<h2>Example step-by-step</h2>
|
2014-11-19 14:58:44 -05:00
|
|
|
<p>In this example we specify a <code>consumer-window-size</code> of <code>0</code> bytes in the <code>activemq-jms.xml</code>
|
2014-10-31 06:20:28 -04:00
|
|
|
file when deploying the connection factory:</p>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>
|
|
|
|
<connection-factory name="ConnectionFactory">
|
|
|
|
<connector-ref connector-name="netty-connector"/>
|
|
|
|
<entries>
|
|
|
|
<entry name="ConnectionFactory"/>
|
|
|
|
</entries>
|
|
|
|
|
|
|
|
<!-- We set the consumer window size to 0, which means messages are not buffered at all
|
|
|
|
on the client side -->
|
|
|
|
<consumer-window-size>0</consumer-window-size>
|
|
|
|
|
|
|
|
</connection-factory>
|
|
|
|
</code>
|
|
|
|
</pre>
|
|
|
|
<p>We create a consumer on a queue and send 10 messages to it. We then create another consumer on
|
|
|
|
the same queue.</p>
|
|
|
|
<p>We then consume messages from each consumer in a semi-random order. We note that the messages
|
|
|
|
are consumed in the order they were sent.</p>
|
|
|
|
<p>If the messages had been buffered in each consumer they would not be available to be consumed
|
|
|
|
in an order determined afer delivery.</p>
|
|
|
|
|
|
|
|
<p><i>To run the example, simply type <code>mvn verify</code> from this directory</i></p>
|
|
|
|
|
|
|
|
<ol>
|
|
|
|
<li>Create an initial context to perform the JNDI lookup.</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>initialContext = getContext(0);</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Perfom a lookup on the queue</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>Queue queue = (Queue)initialContext.lookup("/queue/exampleQueue");</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Perform a lookup on the Connection Factory</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Create a JMS Connection</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>connection = cf.createConnection();</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Create a JMS Session</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Create a JMS MessageProducer</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>MessageProducer producer = session.createProducer(queue);</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Create a JMS MessageConsumer</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>MessageConsumer consumer1 = session.createConsumer(queue);</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Start the connection</li>
|
|
|
|
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>
|
|
|
|
connection.start();
|
|
|
|
</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
|
|
<li>Send 10 messages to the queue</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>
|
|
|
|
final int numMessages = 10;
|
|
|
|
|
|
|
|
for (int i = 0; i < numMessages; i++)
|
|
|
|
{
|
|
|
|
TextMessage message = session.createTextMessage("This is text message: " + i);
|
|
|
|
|
|
|
|
producer.send(message);
|
|
|
|
}
|
|
|
|
</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Create another JMS MessageConsumer on the same queue.</li>
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>MessageConsumer consumer2 = session.createConsumer(queue);</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Consume three messages from consumer2</li>
|
|
|
|
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
TextMessage message = (TextMessage)consumer2.receive(2000);
|
|
|
|
|
|
|
|
System.out.println("Consumed message from consumer2: " + message.getText());
|
|
|
|
}
|
|
|
|
</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Consume five messages from consumer1</li>
|
|
|
|
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
|
|
{
|
|
|
|
TextMessage message = (TextMessage)consumer1.receive(2000);
|
|
|
|
|
|
|
|
System.out.println("Consumed message from consumer1: " + message.getText());
|
|
|
|
}
|
|
|
|
</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<li>Consume two more messages from consumer2</li>
|
|
|
|
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
TextMessage message = (TextMessage)consumer1.receive(2000);
|
|
|
|
|
|
|
|
System.out.println("Consumed message from consumer2: " + message.getText());
|
|
|
|
}
|
|
|
|
</code>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
|
|
<li>Be sure to close our resources!</li>
|
|
|
|
|
|
|
|
<pre class="prettyprint">
|
|
|
|
<code>
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
if (initialContext != null)
|
|
|
|
{
|
|
|
|
initialContext.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (connection != null)
|
|
|
|
{
|
|
|
|
connection.close();
|
|
|
|
}
|
|
|
|
}</code>
|
|
|
|
</pre>
|
|
|
|
</ol>
|
|
|
|
|
|
|
|
<h2>More information</h2>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li>User Manual's <a href="../../../docs/user-manual/en/html_single/index.html#flow-control.consumer.window">Consumer Window-Based Flow Control chapter</a></li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
</body>
|
|
|
|
</html>
|