Jump to: navigation, search

Load Balancing Remote Services

Revision as of 12:19, 11 September 2013 by Slewis.composent.com (Talk | contribs)

Load Balancing ECF Remote Services

ECF's remote services API allows arbitrary services to be exposed for remote access/invocation.

In some cases, such services will be long-running and/or computationally intensive, and this can mean that multiple servers can/should be used to actually execute the given service, so as not to use all resource available on a given server. What would be desirable is that the actual remote service request be dynamically load balanced among some arbitary number of servers, so as not to overload a given server instance.

ECF now has an example that uses the ECF ActiveMQ provider to dynamically load balance individual service requests to an arbitrary number of server processes, thereby distributing the load caused by the service requests onto as many server processes as can be made available. The actual load balancing of individual requests is done by using a JMS Queue, which has load balancing semantics built in.

The load balancing example projects are available in git here

http://git.eclipse.org/c/ecf/org.eclipse.ecf.git

under this part of the tree: examples/bundles

projects: org.eclipse.ecf.examples.loadbalancing, org.eclipse.ecf.examples.loadbalancing.consumer, org.eclipse.ecf.examples.loadbalancing.servicehost, org.eclipse.ecf.examples.loadbalancing.server

Note that you either need to have ECF 3.6.X already installed, or install it in Eclipse or into your workspace's target platform. See here to download/install ECF 3.6.X

Architecture

The load balancing example application starts with a very simple, stateless, service interface called IDataProcessor:

public interface IDataProcessor {

    public String processData(String data);
}

This is a very simple service interface, and is meant to be illustrative/example only. Other services will/should be created as appropriate for one's own application.

The load balancing application is structured as follows:

  1. One or more Service Consumers. The service consumer is the actual client of the remote service (in this case, the client of IDataProcessor service).
  2. A single Service Host, which appears to clients as the actual host of the IDataProcessor service, but is actually a JMS queue producer, which puts method invocation requests (received from the consumers) onto a JMS queue.
  3. One or more Service Servers. The service servers are JMS queue message consumers, so that when a service request is put into the JMS queue, it is then delivered to one and only one queue consumers (as per the JMS Queue semantics). Once received, the appropriate method is invoked on a target service implementation object.

The inter-process communication pattern for these three processes is as follows:

Service Consumer(s) <-JMS topic-> Service Host <-JMS Queue-> Service Server(s)

Running the Example

Starting and Configuring ActiveMQ

  1. To run the example, it's necessary to first install ActiveMQ 5.2+. Once installed, start ActiveMQ by going to the <activemq home> directory, and starting ActiveMQ by giving the bin\activemq command in the <activemq home> directory. This will start an instance of ActiveMQ 5.2+.
  2. With your web browser, go to the ActiveMQ web-based admin interface (by default:http://localhost:8161/admin)
  3. Use the admin interface create a JMS queue with the following name: exampleQueue
  4. Use the admin interface to create a JMS topic with the following name: exampleTopic

Starting the Service Server(s)

  1. In the org.eclipse.ecf.examples.loadbalancing.server project, open the product config by double clicking on the products/Data Processor Server (activemq).product file in the Eclipse package explorer or the navigator. This should open the Eclipse product configuration editor.
  2. In the lower left of the Overview tab, click on the Launch an Eclipse application or the Launch an Eclipse application in Debug mode links. This should launch the data processor server. Note you can start multiple server instances, but you should have at least one running before starting the service host.

On startup, the service server should produce output to the console like this

osgi> SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
LB Server:  Data Processor Registered queue=tcp://localhost:61616/exampleQueue

Starting the Service Host

  1. In the org.eclipse.ecf.examples.loadbalancing.servicehost project, open the product config by double clicking on the products/Data Processor Service Host (activemq).product file in the Eclipse package explorer or the navigator. This should open the Eclipse product configuration editor.
  2. In the lower left of the Overview tab, click on the Launch an Eclipse application or the Launch an Eclipse application in Debug mode links. This should launch the data processor service host. You should start only a single service host.

On startup, the service host should produce output to the console like this

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
osgi> LB Service Host: DataProcessor Registered via ECF Remote Services topic=tcp://localhost:61616/exampleTopic

Running the Service Consumer

  1. In the org.eclipse.ecf.examples.loadbalancing.consumer project, open the product config by double clicking on the products/Data Processor Consumer (activemq).product file in the Eclipse package explorer or the navigator. This should open the Eclipse product configuration editor.
  2. In the lower left of the Overview tab, click on the Launch an Eclipse application or the Launch an Eclipse application in Debug mode links. This should launch the data processor service consumer application.

On startup, the service consumer should produce output to the console like this

osgi> SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Calling remote service with input data=Are we not drawn onward, we few, drawn onward to new era 
	remote service result= are wen ot drawno nward ,wef ew ,drawno nward ton ew erA

The last couple of lines show that the remote IDataProcessor service was invoked with the input data, and produced the given result (reversing the inputData String).

Also, if the Service Server console is consulted after running the Service Consumer, you should see the output of remote call of the Service Server implementation object:

DataProcessorImpl(7MpbrpeWXUZHDElu681E5er7VRw=).processData data=Are we not drawn onward, we few, drawn onward to new era 

If more than one Service Server is started, then each consumer invocation will be load balanced among the Service Servers.

Classes to examine in source

Service Server

org.eclipse.ecf.internal.examples.loadbalancing.server.DataProcessorServerApplication org.eclipse.ecf.internal.examples.loadbalancing.server.DataProcessorImpl

Service Host

org.eclipse.ecf.internal.examples.loadbalancing.servicehost.DataProcessorServiceHostApplication

Service Consumer

org.eclipse.ecf.internal.examples.loadbalancing.consumer.DataProcessorConsumerApplication