Apache Camel Load Balancer

0

Load balancing is a technique to distribute workload across computers or other resources. This helps us to make best use of our resources thus maximize throughput, minimize response time, and avoid overload.
Suppose your application is hosted in a cluster of machines where each one has the ability to process the incoming message then you can distribute the messages received using Camel’s load balancer so that no one machine is overloaded.

This example uses the following frameworks:

  1. Maven 3.2.3
  2. Apache Camel 2.15.1
  3. Spring 4.1.5.RELEASE
  4. Eclipse  as the IDE, version Luna 4.4.1.

Dependencies

We are just relying camel’s core components, the spring based components and the logger component in case you want to log something so our pom.xml consists of:

  1. camel-core – camel core components like timer, bean etc
  2. slf4j-api – in case you want to use log
  3. slf4j-log4j12 – if you want to use log4j as the slf4j implementation
  4. camel-stream – for printing the messages to console
  5. spring-context and spring-core – for spring support
  6. camel-spring – include it if you want to define route in spring

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javarticles.camel</groupId>
	<artifactId>camelContentBasedRouting</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-core</artifactId>
			<version>2.15.2</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.12</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.12</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.1.5.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-spring</artifactId>
			<version>2.15.2</version>
		</dependency>	
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-stream</artifactId>
			<version>2.15.2</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>4.1.5.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.1.5.RELEASE</version>
		</dependency>	
	</dependencies>
</project>

Camel Load Balancer Using Round Robin Strategy

Camel load balancer allows you to delegate to one of a number of endpoints using a variety of different load balancing policies. Let’s see an example load balancer that uses the round robin strategy. In a round robin strategy, the first message goes to the first endpoint, the second to the second endpoint, the third to the third endpoint, the fourth back will repeat itself from the first endpoint, and so on.

CamelLoadbalanceRoundRobinExample:

package com.javarticles.camel;

import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;

public class CamelLoadbalanceRoundRobinExample {
    public static void main(String[] args) throws Exception {
        CamelContext camelContext = new DefaultCamelContext();        
        try {
            camelContext.addRoutes(new RouteBuilder() {
                public void configure() {                    
                    from("timer:myTimer?period=1s")
                    .loadBalance()
                    .roundRobin()
                    .to("direct:a")
                    .to("direct:b")
                    .to("direct:c");
                    
                    from("direct:a")
                    .setBody()
                    .constant("Endpoint Direct a")
                    .to("stream:out");
                    
                    from("direct:b")
                    .setBody()
                    .constant("Endpoint Direct b")
                    .to("stream:out");
                    
                    from("direct:c")
                    .setBody()
                    .constant("Endpoint Direct c")
                    .to("stream:out");
                }
            });
            camelContext.start();
            Thread.sleep(10000);
        } finally {
            camelContext.stop();
        }
    }

}

Round robin strategy is the simplest of the pre-defined strategies, as you can see, The first message is sent to the “direct:a” endpoint, and the next would go to “direct:b” and then to “direct:c”. The fourth message would start over with “direct:a”, and so forth.

Output:

Endpoint Direct a
Endpoint Direct b
Endpoint Direct c
Endpoint Direct a
Endpoint Direct b
Endpoint Direct c
Endpoint Direct a
Endpoint Direct b
Endpoint Direct c

Load Balancer Using Random Strategy

When the load balancer receives a message, it depends on the load balancing strategy to decide which Processor to chose to process the message. We have seen the round robin strategy. In this example, we will see random load balancing strategy. As the name suggests, it chooses a processor randomly. In java DSL, we will call method random() to set the random strategy.

CamelLoadbalanceRandomExample:

package com.javarticles.camel;

import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;

public class CamelLoadbalanceRandomExample {
    public static void main(String[] args) throws Exception {
        CamelContext camelContext = new DefaultCamelContext();        
        try {
            camelContext.addRoutes(new RouteBuilder() {
                public void configure() {                    
                    from("timer:myTimer?period=1s")
                    .loadBalance()
                    .random()
                    .to("direct:a")
                    .to("direct:b")
                    .to("direct:c");
                    
                    from("direct:a")
                    .setBody()
                    .constant("Endpoint Direct a")
                    .to("stream:out");
                    
                    from("direct:b")
                    .setBody()
                    .constant("Endpoint Direct b")
                    .to("stream:out");
                    
                    from("direct:c")
                    .setBody()
                    .constant("Endpoint Direct c")
                    .to("stream:out");
                }
            });
            camelContext.start();
            Thread.sleep(10000);
        } finally {
            camelContext.stop();
        }
    }

}

Output:

Endpoint Direct b
Endpoint Direct b
Endpoint Direct a
Endpoint Direct c
Endpoint Direct b
Endpoint Direct c
Endpoint Direct b
Endpoint Direct a
Endpoint Direct a

Load Balancing Using Spring DSL

Here is the equivalent route in spring DSL. The endpoints that are load balanced will be declared within <loadBalance> element. The first element will define the load balancing strategy. Our strategy is round robin so we will simply add an empty tag <roundRobin />. If it is random strategy, you need to add <roundRobin />.

loadBalancingRoundRobinCamelContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd		
		http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

	<camelContext xmlns="http://camel.apache.org/schema/spring">
		<route>
			<from uri="timer:myTimer?period=1s" />
			<loadBalance>
				<roundRobin />
				<to uri="direct:a" />
				<to uri="direct:b" />
				<to uri="direct:c" />
			</loadBalance>
		</route>

		<route>
			<from uri="direct:a" />
			<setBody>
				<constant>Endpoint Direct a</constant>
			</setBody>
			<to uri="stream:out" />
		</route>

		<route>
			<from uri="direct:b" />
			<setBody>
				<constant>Endpoint Direct b</constant>
			</setBody>			
			<to uri="stream:out" />
		</route>

		<route>
			<from uri="direct:c" />
			<setBody>
				<constant>Endpoint Direct c</constant>
			</setBody>			
			<to uri="stream:out" />
		</route>
	</camelContext>

</beans>

CamelLoadBalanceRoundRobinUsingSpring:

package com.javarticles.camel;

import org.apache.camel.CamelContext;
import org.apache.camel.spring.SpringCamelContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class CamelLoadBalanceRoundRobinUsingSpring {
    public static final void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
                "loadBalancingRoundRobinCamelContext.xml");
        CamelContext camelContext = SpringCamelContext.springCamelContext(
                appContext, false);
        try {            
            camelContext.start();            
            Thread.sleep(5000);
        } finally {
            camelContext.stop();
            appContext.close();
        }
    }
}

Output:

Endpoint Direct a
Endpoint Direct b
Endpoint Direct c
Endpoint Direct a
Endpoint Direct b

Download the source code

This was an example about Apache Camel’s Load Balancer.

You can download the source code here: camelLoadbalanceExample.zip
Share.

Comments are closed.