I have a Spring integration app, attached to an AMQP broker.
I want to receive messages from an amqp-queue, and update db records.
In order to improve perfor
Rather than using a QueueChannel
and poller, why not simply increase the concurrent-consumers
attribute on the inbound adapter?
<xsd:attribute name="concurrent-consumers" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Specify the number of concurrent consumers to create. Default is 1.
Raising the number of concurrent consumers is recommended in order to scale the consumption of messages coming in
from a queue. However, note that any ordering guarantees are lost once multiple consumers are registered. In
general, stick with 1 consumer for low-volume queues.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
And, remove the <queue/>
and <poller/>
.
Also, I always recommend including the thread name in the log (%t
for log4J); it makes it easier to debug threading issues.
EDIT:
With the poller, the reason you are running out of threads is the poller has a default receive-timeout
of 1 second. You are scheduling a thread every 50ms, but each then waits in the QueueChannel
for 1 second. Eventually your task queue fills up.
To avoid this, simply set the receive-timeout
to 0
on the <poller/>
if you wish to continue with this technique - but using higher concurrency in the adapter is more efficient because there's no polling or handover to another thread.
It appears I needed a bridge to map between the amqp-inbound queue (which is a pub/sub style queue), and a queue-channel.
<int-amqp:inbound-channel-adapter queue-names="pricehub.fixtures.priceUpdates.queue"
channel="pricehub.fixtures.priceUpdates.subpub"
message-converter="jsonMessageConverter"/>
<int:publish-subscribe-channel id="pricehub.fixtures.priceUpdates.subpub" />
<int:bridge input-channel="pricehub.fixtures.priceUpdates.subpub"
output-channel="pricehub.fixtures.priceUpdates.channel" />
<int:channel id="pricehub.fixtures.priceUpdates.channel">
<int:queue />
</int:channel>
<int:service-activator ref="updatePriceAction"
method="updatePrices"
input-channel="pricehub.instruments.priceUpdates.channel">
<int:poller fixed-delay="50" time-unit="MILLISECONDS" task-executor="taskExecutor" />
</int:service-activator>
<task:executor id="taskExecutor" pool-size="5-50" keep-alive="120" queue-capacity="500"/>
This seems like a LOT of code to achieve a fairly trivial task - so if anyone has better solutions, or suggestions for improvements, I'd love to see them.