Avijit Gupta
Avijit Gupta

Reputation: 3

Camel Failover Load Balancer not failing over to next target if a Dead Letter Channel Error Handler is defined in the route

I have defined a camel route using a failover load balancer like this:

from(activemq:foo)
    .errorHandler(deadLetterChannel(activemq:foo.dlq).onPrepareFailure(failureProcessor))
    .process(processor)
    .loadBalance()
        .failover(2, true, true)
            .to(activemq:queue1, activemq:queue2)
    .end();

With the above-defined route, if delivery to queue1 fails, the exception is handled by the error handler and message is put directly into foo.dlq without load balancer failing over to the next target.

How do I define a route:
Which should failover to all the routes and if delivery to all of them fails (fails entirely), it should then send the control to error handler which should put the message to DLQ.

Upvotes: 0

Views: 302

Answers (2)

TacheDeChoco
TacheDeChoco

Reputation: 3913

I'm surprised. I have just run the following test (in Camel 3.9) - with 2 dummy http endpoints:

from("timer://demo?period=60s")
    .errorHandler( deadLetterChannel("log:DLQ") )
    .log("Run")
    .loadBalance().failover(2, false, false)
        .to("direct:node1")
        .to("direct:node2")
    .end()
    .log("success");

from("direct:node1")
    .errorHandler( noErrorHandler() )
    .log("Attempt on node#1")
    .to("http://localhost:8881/ws");

from("direct:node2")
    .errorHandler( noErrorHandler() )
    .log("Attempt on node#2")
    .to("http://localhost:8882/ws");

And here is the output:

INFO  | route1                         | Camel (Test) thread #0 - t | Run
INFO  | route2                         | Camel (Test) thread #0 - t | Attempt on node#1
INFO  | route3                         | Camel (Test) thread #0 - t | Attempt on node#2
INFO  | DLQ                            | Camel (Test) thread #0 - t | Exchange[ExchangePattern: InOnly, BodyType: null, Body: [Body is null]]

You clearly see that there is one attempt on each node, and the exchange finally goes to the DLQ

If i enable inheritErrorHandler, the output is now:

INFO  | route1                         | Camel (Test) thread #0 - t | Run
INFO  | route2                         | Camel (Test) thread #0 - t | Attempt on node#1
INFO  | DLQ                            | Camel (Test) thread #0 - t | Exchange[ExchangePattern: InOnly, BodyType: null, Body: [Body is null]]

Upvotes: 0

TacheDeChoco
TacheDeChoco

Reputation: 3913

I think you should turn inheritErrorHandler (2nd param) to off in your load balancer, ie:

.loadBalance()
   .failover(2, false, true)

This way, any failure on one of the two nodes gets propagated to the loadBalancer processor rather than to the DLQ.

But if the whole loadbalancing process fails (that is: if both nodes fail), the DLQ will be kicked in.

Hint: if you indent your code, the propagation logic is a bit more clear:

from("...")
  .errorHandler(...)
  .loadBalance().failover(2, false, true) // level 1
    .to("...") // level 2
    .to("...") // level 2
  .end();

You have two identation levels; each level having its own error handling:

  • errors of level 2 are managed by the load balancer
  • errors of level 1 are managed by the DLQ

Upvotes: 0

Related Questions