Load BalancerThe Load Balancer Pattern allows you to delegate to one of a number of endpoints using a variety of different load balancing policies. Built-in load balancing policiesCamel provides the following policies out-of-the-box:
Round RobinThe round robin load balancer is not meant to work with failover, for that you should use the dedicated failover load balancer. The round robin load balancer will only change to next endpoint per message. The round robin load balancer is stateful as it keeps state of which endpoint to use next time. Using the Fluent Builders from("direct:start").loadBalance(). roundRobin().to("mock:x", "mock:y", "mock:z"); Using the Spring configuration <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="direct:start"/> <loadBalance> <roundRobin/> <to uri="mock:x"/> <to uri="mock:y"/> <to uri="mock:z"/> </loadBalance> </route> </camelContext> The above example loads balance requests from direct:start to one of the available mock endpoint instances, in this case using a round robin policy. FailoverThe failover load balancer is capable of trying the next processor in case an Exchange failed with an exception during processing.
Failover offers the following options:
Camel 2.2 or older behavior Camel 2.3 onwards behavior
Here is a sample to failover only if a IOException related exception was thrown: from("direct:start") // here we will load balance if IOException was thrown // any other kind of exception will result in the Exchange as failed // to failover over any kind of exception we can just omit the exception // in the failOver DSL .loadBalance().failover(IOException.class) .to("direct:x", "direct:y", "direct:z"); You can specify multiple exceptions to failover as the option is varargs, for instance: // enable redelivery so failover can react errorHandler(defaultErrorHandler().maximumRedeliveries(5)); from("direct:foo"). loadBalance().failover(IOException.class, MyOtherException.class) .to("direct:a", "direct:b"); Using failover in Spring DSLFailover can also be used from Spring DSL and you configure it as: <route errorHandlerRef="myErrorHandler"> <from uri="direct:foo"/> <loadBalance> <failover> <exception>java.io.IOException</exception> <exception>com.mycompany.MyOtherException</exception> </failover> <to uri="direct:a"/> <to uri="direct:b"/> </loadBalance> </route> Using failover in round robin modeAn example using Java DSL: from("direct:start") // Use failover load balancer in stateful round robin mode // which mean it will failover immediately in case of an exception // as it does NOT inherit error handler. It will also keep retrying as // its configured to newer exhaust. .loadBalance().failover(-1, false, true). to("direct:bad", "direct:bad2", "direct:good", "direct:good2"); And the same example using Spring XML: <route> <from uri="direct:start"/> <loadBalance> <!-- failover using stateful round robin, which will keep retrying forever those 4 endpoints until success. You can set the maximumFailoverAttempt to break out after X attempts --> <failover roundRobin="true"/> <to uri="direct:bad"/> <to uri="direct:bad2"/> <to uri="direct:good"/> <to uri="direct:good2"/> </loadBalance> </route>
Weighted Round-Robin and Random Load BalancingAvailable as of Camel 2.5 In many enterprise environments where server nodes of unequal processing power & performance characteristics are utilized to host services and processing endpoints, it is frequently necessary to distribute processing load based on their individual server capabilities so that some endpoints are not unfairly burdened with requests. Obviously simple round-robin or random load balancing do not alleviate problems of this nature. A Weighted Round-Robin and/or Weighted Random load balancer can be used to address this problem. The weighted load balancing policy allows you to specify a processing load distribution ratio for each server with respect to others. You can specify this as a positive processing weight for each server. A larger number indicates that the server can handle a larger load. The weight is utilized to determine the payload distribution ratio to different processing endpoints with respect to others.
The parameters that can be used are In Camel 2.5
Available In Camel 2.6
Using Weighted round-robin & random load balancingIn Camel 2.5 An example using Java DSL: ArrayList<integer> distributionRatio = new ArrayList<integer>(); distributionRatio.add(4); distributionRatio.add(2); distributionRatio.add(1); // round-robin from("direct:start") .loadBalance().weighted(true, distributionRatio) .to("mock:x", "mock:y", "mock:z"); //random from("direct:start") .loadBalance().weighted(false, distributionRatio) .to("mock:x", "mock:y", "mock:z"); And the same example using Spring XML:
<route>
<from uri="direct:start"/>
<loadBalance>
<weighted roundRobin="false" distributionRatio="4 2 1"/>
<to uri="mock:x"/>
<to uri="mock:y"/>
<to uri="mock:z"/>
</loadBalance>
</route>
Available In Camel 2.6 An example using Java DSL: // round-robin from("direct:start") .loadBalance().weighted(true, "4:2:1" distributionRatioDelimiter=":") .to("mock:x", "mock:y", "mock:z"); //random from("direct:start") .loadBalance().weighted(false, "4,2,1") .to("mock:x", "mock:y", "mock:z"); And the same example using Spring XML:
<route>
<from uri="direct:start"/>
<loadBalance>
<weighted roundRobin="false" distributionRatio="4-2-1" distributionRatioDelimiter="-" />
<to uri="mock:x"/>
<to uri="mock:y"/>
<to uri="mock:z"/>
</loadBalance>
</route>
Custom Load BalancerYou can use a custom load balancer (eg your own implementation) also. An example using Java DSL: from("direct:start") // using our custom load balancer .loadBalance(new MyLoadBalancer()) .to("mock:x", "mock:y", "mock:z"); And the same example using XML DSL: <!-- this is the implementation of our custom load balancer --> <bean id="myBalancer" class="org.apache.camel.processor.CustomLoadBalanceTest$MyLoadBalancer"/> <camelContext xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="direct:start"/> <loadBalance> <!-- refer to my custom load balancer --> <custom ref="myBalancer"/> <!-- these are the endpoints to balancer --> <to uri="mock:x"/> <to uri="mock:y"/> <to uri="mock:z"/> </loadBalance> </route> </camelContext> Notice in the XML DSL above we use <custom> which is only available in Camel 2.8 onwards. In older releases you would have to do as follows instead:
<loadBalance ref="myBalancer">
<!-- these are the endpoints to balancer -->
<to uri="mock:x"/>
<to uri="mock:y"/>
<to uri="mock:z"/>
</loadBalance>
To implement a custom load balancer you can extend some support classes such as LoadBalancerSupport and SimpleLoadBalancerSupport. The former supports the asynchronous routing engine, and the latter does not. Here is an example: Custom load balancer implementation public static class MyLoadBalancer extends LoadBalancerSupport { public boolean process(Exchange exchange, AsyncCallback callback) { String body = exchange.getIn().getBody(String.class); try { if ("x".equals(body)) { getProcessors().get(0).process(exchange); } else if ("y".equals(body)) { getProcessors().get(1).process(exchange); } else { getProcessors().get(2).process(exchange); } } catch (Throwable e) { exchange.setException(e); } callback.done(true); return true; } } Using This PatternIf you would like to use this EIP Pattern then please read the Getting Started, you may also find the Architecture useful particularly the description of Endpoint and URIs. Then you could try out some of the Examples first before trying this pattern out. |