Reputation: 3
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
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
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:
Upvotes: 0