Thursday, October 14, 2010

Added support for Weighted Round-Robin and Weighted Random Load balancing in Camel

I have just added a new capability in Camel 2.5, to offer Weighted Round-Robin and Weighted Random Load Balancer support.

Camel currently offers several different Load Balancing policies out of the box such as
  • Round-Robin
  • Random
  • Sticky
  • Topic Based and
  • Fail-over
However, 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 is invaluable in this regard.

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.

In addition to the weight, endpoint selection is then further refined based on an algorithm (round-robin/random).

Weighted Round Robin Load Balancing

Given below is a Camel example of the weighted round-robin capability in action. Note that there are 3 mock camel endpoints (mock:x, mock:y and mock:z). The important thing is to associate a distribution ratio (list of server weights) and wire it into a load balancer on the route  along with a boolean value (specifying whether the distribution algorithm is round-robin (true in this case).

In the example below we expect endpoints mock:x, mock:y and mock:z to receive 4, 2 and 1 messages  out of every 7 messages respectively. In addition we expect each endpoint to receive messages in strict round-robin order until its weight no longer permits further delivery of messages until the next cycle.

public void testRoundRobin() throws Exception {

        x.expectedMessageCount(5);
        y.expectedMessageCount(2);
        z.expectedMessageCount(1);

        context.addRoutes(new RouteBuilder() {
            public void configure() {
                ArrayList distributionRatio = new ArrayList();
                distributionRatio.add(4);
                distributionRatio.add(2);
                distributionRatio.add(1);
                
                // START SNIPPET: example
                from("direct:start").loadBalance().
                weighted(true, distributionRatio).to("mock:x", "mock:y", "mock:z");
                // END SNIPPET: example
            }
        });
        context.start();
        
        sendMessages(1, 2, 3, 4, 5, 6, 7, 8);
        
        assertMockEndpointsSatisfied();
        x.expectedBodiesReceived(1, 4, 6, 7, 8);
        y.expectedBodiesReceived(2, 5);
        z.expectedBodiesReceived(3);
    }

Weighted Random Load Balancing

Given below is a Camel example of the weighted round-robin capability in action. Note that there are 3 mock camel endpoints (mock:x, mock:y and mock:z). Again in this case, the important thing is to associate a distribution ratio (list of server weights) and wire it into a load balancer on the route  along with a boolean value (specifying whether the distribution algorithm is round-robin (false in this case).

In the example below we expect endpoints mock:x, mock:y and mock:z to receive 4, 2 and 1 messages out of every 7 messages respectively. In addition we expect each endpoint to receive messages in a random order until its weight no longer permits further delivery of messages until the next cycle.

public void testRandom() throws Exception {

        x.expectedMessageCount(4);
        y.expectedMessageCount(2);
        z.expectedMessageCount(1);

        context.addRoutes(new RouteBuilder() {
            public void configure() {
                ArrayList distributionRatio = new ArrayList();
                distributionRatio.add(4);
                distributionRatio.add(2);
                distributionRatio.add(1);
                
                // START SNIPPET: example
                from("direct:start").loadBalance().
                weighted(false, distributionRatio).to("mock:x", "mock:y", "mock:z");
                // END SNIPPET: example
            }
        });
        context.start();
        
        sendMessages(1, 2, 3, 4, 5, 6, 7);
        
        assertMockEndpointsSatisfied();
    }

Complete Examples
WeightedRoundRobinLoadBalanceTest
WeightedRandomLoadBalanceTest

Further Details
https://issues.apache.org/activemq/browse/CAMEL-3197

No comments: