You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Frank Ertl <fr...@f-i-solutions-plus.de> on 2015/03/20 17:40:49 UTC

How to avoid blocking threads in JmsComponent with Oracle AQ

Hi guys,

we have the following scenario:

Orders are stored to an Oracle AQ queue from where we read the messages by a
JmsComponent and deliver the content to a webservice.
If anything goes wrong we should redeliver the messages with exponential
backoff starting with a delay of 15 minutes.

    errorHandler(deadLetterChannel(MANUAL_QUEUE_CHANNEL_URI)
        .asyncDelayedRedelivery()
        .maximumRedeliveries(8)
        .redeliveryDelay(900000)
        .onRedelivery(waitingStateProcessor)
        .backOffMultiplier(2)
        .retryAttemptedLogLevel(LoggingLevel.INFO)
        .retriesExhaustedLogLevel(LoggingLevel.ERROR));
		
	from("jms:order_queue")
        .process(orderProcessor)
        .to("cxf:bean:orderWS");

Because we don't want to loose any orders in case of a server crash the
JsmComponent is set to transacted. Reading the documentation I came to the
conclusion that asyncDelayedRedelivery() does not work for transacted
routes, which proofs to be true as the threads are blocked when the failed
messages reaches the maximum threadcount.

Is there another way with camel to do the required redelivery without
blocking the threads? Using a timer?

Regards,
Frank



--
View this message in context: http://camel.465427.n5.nabble.com/How-to-avoid-blocking-threads-in-JmsComponent-with-Oracle-AQ-tp5764487.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: How to avoid blocking threads in JmsComponent with Oracle AQ

Posted by Frank Ertl <fr...@f-i-solutions-plus.de>.
Hi Preben,

a real snip would be really useful indeed. 
Still I'm not shure how this is going to work, taking into account that the
last backoffintervall will be 12 hours. 

Regards,
Frank




--
View this message in context: http://camel.465427.n5.nabble.com/How-to-avoid-blocking-threads-in-JmsComponent-with-Oracle-AQ-tp5764487p5764560.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: How to avoid blocking threads in JmsComponent with Oracle AQ

Posted by "Preben.Asmussen" <pr...@dr.dk>.
Hi Frank

We are using AQ too so i know some of the challenges. 
In some case we use a mix of broker redelivery and camel exception handler
with backoff.
I can't remember it from my the top of my head but here is some sudocode ->

from("oracleaq:myqueue?concurrentConsumers=20")
transacted
  onexception(exception e)
    do some backoff, but within db transaction timeout - at the backoff
don't handle the exception, and let the transaction  rollback. This will
cause broker redelivery
  end;
...........................


If useful for you I can update the post with a real snip when I get back at
work.

Best,
Preben




--
View this message in context: http://camel.465427.n5.nabble.com/How-to-avoid-blocking-threads-in-JmsComponent-with-Oracle-AQ-tp5764487p5764558.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: How to avoid blocking threads in JmsComponent with Oracle AQ

Posted by Frank Ertl <fr...@f-i-solutions-plus.de>.
Hi Preben, 

yeah, redelivery is no problem creating the queue, exponential backoff is...
You can have a workaroung using propagation but this leads to logic
distribution as I mentioned in my answer to Claus above. Unfortunately the
exponential backoff is definitely required. Perhaps we should move to
ActiveMQ (my favourite, but I was outnumbered in the decision)

Regards,
Frank



--
View this message in context: http://camel.465427.n5.nabble.com/How-to-avoid-blocking-threads-in-JmsComponent-with-Oracle-AQ-tp5764487p5764557.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: How to avoid blocking threads in JmsComponent with Oracle AQ

Posted by "Preben.Asmussen" <pr...@dr.dk>.
Hi

As Claus said you should favor using broker redelivery when using jms. 
You can do that on OracleAQ when creating the queue/topic with a specifik
redelivery delay. Backoff is not supported afair. But look at the Oracle
docs.

There is a catch though. Message ordering is not guaranteed during
redelivery, but I think that's common for most jms brokers.

/Preben



--
View this message in context: http://camel.465427.n5.nabble.com/How-to-avoid-blocking-threads-in-JmsComponent-with-Oracle-AQ-tp5764487p5764542.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: How to avoid blocking threads in JmsComponent with Oracle AQ

Posted by Frank Ertl <fr...@f-i-solutions-plus.de>.
Hi Claus,

thanks for the info, even if that's not what I hoped for 
In fact it's not so easy to do this things with OracleAQ, furthermore it
leeds to distributing logic between application and database which should be
avoided IMHO.

By the way I already configured asyncConsumer=true

My JmsComponent looks like this at the moment:

  JmsComponent jmsComponent = new JmsComponent();
    JmsConfiguration jmsConfiguration = new JmsConfiguration();
    jmsConfiguration.setConnectionFactory(jmsConnectionFactory);
    jmsComponent.setConfiguration(jmsConfiguration);
    jmsComponent.setDestinationResolver(destinationResolver);
    jmsComponent.setAcceptMessagesWhileStopping(false);
    jmsComponent.setTransacted(false);
    jmsComponent.setReceiveTimeout(JmsTemplate.RECEIVE_TIMEOUT_NO_WAIT);
    jmsComponent.setMaxConcurrentConsumers(20);
    jmsComponent.setAsyncConsumer(true);
    camelContext.addComponent("jms", jmsComponent);

The weird thing is: I tried (just out of curiosity) to set
jmsComponent.setTransacted(false); as you can see.
Debugging the RedliveryErrorHandler I found that seems to work, as in the
process-Method the correct condition is matched and the following line is
execcuted:

executorService.schedule(task, data.redeliveryDelay, TimeUnit.MILLISECONDS);

Nevertheless, it seems this is not working, too. Posting 500 messages to the
queue with above said redeliverydelay I can see the configured 20 consumers
read the first 20 messages and fail in the log (as intended by our
testcase). After that: nothing. The system seems to be completely blocked. I
would have expected that in this case the failing messages would be
scheduled and the consumers would go through the next 20 messages and so on.
Have I overlooked something in the documentation?

Oh, and sorry that I forgot that the "crystal ball" module is still not
implemented in nabble : we are using Camel 2.14.1 with Spring 4.1.5
(javaconfig, not xml) and Java 8




--
View this message in context: http://camel.465427.n5.nabble.com/How-to-avoid-blocking-threads-in-JmsComponent-with-Oracle-AQ-tp5764487p5764556.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: How to avoid blocking threads in JmsComponent with Oracle AQ

Posted by Claus Ibsen <cl...@gmail.com>.
Hi

Oh to not block on the jms consumer you need to configure it to
asyncConsumer=true. Then when the error handler does schedule a async
redelivery, the consumer thread is not blocked, and can work on the
next message.

But again long lasting transactions and redeliveries is likely better
if the broker can schedule them.
If not make sure to give it a bit of test spin to ensure it works well
with your OracleAQ broker.



On Sat, Mar 21, 2015 at 6:55 AM, Claus Ibsen <cl...@gmail.com> wrote:
> Hi
>
> You should favor using the brokers redelivery settings instead of
> Camel. Then you dont have blocked threads, or long running
> transactions. Using Camel is better for short term redeliveries.
>
> OracleAQ from such a big player must surely have some way of
> configuring redelivery.
>
> Apache ActiveMQ do have that.
> http://activemq.apache.org/redelivery-policy.html
>
> On Fri, Mar 20, 2015 at 5:40 PM, Frank Ertl
> <fr...@f-i-solutions-plus.de> wrote:
>> Hi guys,
>>
>> we have the following scenario:
>>
>> Orders are stored to an Oracle AQ queue from where we read the messages by a
>> JmsComponent and deliver the content to a webservice.
>> If anything goes wrong we should redeliver the messages with exponential
>> backoff starting with a delay of 15 minutes.
>>
>>     errorHandler(deadLetterChannel(MANUAL_QUEUE_CHANNEL_URI)
>>         .asyncDelayedRedelivery()
>>         .maximumRedeliveries(8)
>>         .redeliveryDelay(900000)
>>         .onRedelivery(waitingStateProcessor)
>>         .backOffMultiplier(2)
>>         .retryAttemptedLogLevel(LoggingLevel.INFO)
>>         .retriesExhaustedLogLevel(LoggingLevel.ERROR));
>>
>>         from("jms:order_queue")
>>         .process(orderProcessor)
>>         .to("cxf:bean:orderWS");
>>
>> Because we don't want to loose any orders in case of a server crash the
>> JsmComponent is set to transacted. Reading the documentation I came to the
>> conclusion that asyncDelayedRedelivery() does not work for transacted
>> routes, which proofs to be true as the threads are blocked when the failed
>> messages reaches the maximum threadcount.
>>
>> Is there another way with camel to do the required redelivery without
>> blocking the threads? Using a timer?
>>
>> Regards,
>> Frank
>>
>>
>>
>> --
>> View this message in context: http://camel.465427.n5.nabble.com/How-to-avoid-blocking-threads-in-JmsComponent-with-Oracle-AQ-tp5764487.html
>> Sent from the Camel - Users mailing list archive at Nabble.com.
>
>
>
> --
> Claus Ibsen
> -----------------
> Red Hat, Inc.
> Email: cibsen@redhat.com
> Twitter: davsclaus
> Blog: http://davsclaus.com
> Author of Camel in Action: http://www.manning.com/ibsen
> hawtio: http://hawt.io/
> fabric8: http://fabric8.io/



-- 
Claus Ibsen
-----------------
Red Hat, Inc.
Email: cibsen@redhat.com
Twitter: davsclaus
Blog: http://davsclaus.com
Author of Camel in Action: http://www.manning.com/ibsen
hawtio: http://hawt.io/
fabric8: http://fabric8.io/

Re: How to avoid blocking threads in JmsComponent with Oracle AQ

Posted by Claus Ibsen <cl...@gmail.com>.
Hi

You should favor using the brokers redelivery settings instead of
Camel. Then you dont have blocked threads, or long running
transactions. Using Camel is better for short term redeliveries.

OracleAQ from such a big player must surely have some way of
configuring redelivery.

Apache ActiveMQ do have that.
http://activemq.apache.org/redelivery-policy.html

On Fri, Mar 20, 2015 at 5:40 PM, Frank Ertl
<fr...@f-i-solutions-plus.de> wrote:
> Hi guys,
>
> we have the following scenario:
>
> Orders are stored to an Oracle AQ queue from where we read the messages by a
> JmsComponent and deliver the content to a webservice.
> If anything goes wrong we should redeliver the messages with exponential
> backoff starting with a delay of 15 minutes.
>
>     errorHandler(deadLetterChannel(MANUAL_QUEUE_CHANNEL_URI)
>         .asyncDelayedRedelivery()
>         .maximumRedeliveries(8)
>         .redeliveryDelay(900000)
>         .onRedelivery(waitingStateProcessor)
>         .backOffMultiplier(2)
>         .retryAttemptedLogLevel(LoggingLevel.INFO)
>         .retriesExhaustedLogLevel(LoggingLevel.ERROR));
>
>         from("jms:order_queue")
>         .process(orderProcessor)
>         .to("cxf:bean:orderWS");
>
> Because we don't want to loose any orders in case of a server crash the
> JsmComponent is set to transacted. Reading the documentation I came to the
> conclusion that asyncDelayedRedelivery() does not work for transacted
> routes, which proofs to be true as the threads are blocked when the failed
> messages reaches the maximum threadcount.
>
> Is there another way with camel to do the required redelivery without
> blocking the threads? Using a timer?
>
> Regards,
> Frank
>
>
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/How-to-avoid-blocking-threads-in-JmsComponent-with-Oracle-AQ-tp5764487.html
> Sent from the Camel - Users mailing list archive at Nabble.com.



-- 
Claus Ibsen
-----------------
Red Hat, Inc.
Email: cibsen@redhat.com
Twitter: davsclaus
Blog: http://davsclaus.com
Author of Camel in Action: http://www.manning.com/ibsen
hawtio: http://hawt.io/
fabric8: http://fabric8.io/