Difference between revisions of "Load Balancing Remote Services"

From Eclipsepedia

Jump to: navigation, search
(Architecture)
(Starting and Configuring ActiveMQ)
Line 45: Line 45:
  
 
# To run the example, it's necessary to first install [http://activemq.apache.org/download.html ActiveMQ 5.2].  Once installed, start ActiveMQ by going to the '''<activemq home>/bin''' directory, and starting ActiveMQ by giving the '''activemq''' command in the <activemq home>/bin directory.  This will start an instance of ActiveMQ 5.2.
 
# To run the example, it's necessary to first install [http://activemq.apache.org/download.html ActiveMQ 5.2].  Once installed, start ActiveMQ by going to the '''<activemq home>/bin''' directory, and starting ActiveMQ by giving the '''activemq''' command in the <activemq home>/bin directory.  This will start an instance of ActiveMQ 5.2.
# With your web browser, go to the ActiveMQ web-based admin interface: '''http://localhost:8161/admin'''
+
# With your web browser, go to the ActiveMQ web-based admin interface (by default:'''http://localhost:8161/admin''')
# Create a JMS queue with the following name:  '''exampleQueue'''
+
# Use the admin interface create a JMS queue with the following name:  '''exampleQueue'''
# Create a JMS topic with the following name:  '''exampleTopic'''
+
# Use the admin interface to create a JMS topic with the following name:  '''exampleTopic'''
  
 
====Starting the Service Server(s)====
 
====Starting the Service Server(s)====

Revision as of 21:51, 19 October 2009

Contents

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 CVS:

CVS root: /cvsroot/rt module: org.eclipse.ecf/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

Or you can use this project set file to load the 4 example projects into directly into your Eclipse workspace.

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

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>/bin directory, and starting ActiveMQ by giving the activemq command in the <activemq home>/bin 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

Registered data processor.  Remote service registration=RemoteServiceRegistrationImpl[remoteServiceID=org.eclipse.ecf.remoteservice.RemoteServiceID[containerID=JMSID[Vf/B9giiOv3dCEQrAVKPrREJgBY=];containerRelativeID=0];containerID=JMSID[Vf/B9giiOv3dCEQrAVKPrREJgBY=];serviceid=0;serviceranking=0;classes=[org.eclipse.ecf.examples.loadbalancing.IDataProcessor];state=0;properties={ecf.rsvc.id=0}]

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

<ActiveMQ 5.2 spurious WARNING and exception stack...see ActiveMQ bug:  https://issues.apache.org/activemq/browse/AMQ-2256>
Registered service host with registration=RemoteServiceRegistrationImpl[remoteServiceID=org.eclipse.ecf.remoteservice.RemoteServiceID[containerID=JMSID[tcp://localhost:61616/exampleTopic];containerRelativeID=0];containerID=JMSID[tcp://localhost:61616/exampleTopic];serviceid=0;serviceranking=0;classes=[org.eclipse.ecf.examples.loadbalancing.IDataProcessor];state=0;properties={ecf.rsvc.id=0, jms.queue.loadbalance=true}]

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

<ActiveMQ 5.2 spurious WARNING and exception stack...see ActiveMQ bug:  https://issues.apache.org/activemq/browse/AMQ-2256>
Calling remote service ref=RemoteServiceReferenceImpl[class=org.eclipse.ecf.examples.loadbalancing.IDataProcessor;registration=RemoteServiceRegistrationImpl[remoteServiceID=org.eclipse.ecf.remoteservice.RemoteServiceID[containerID=JMSID[tcp://localhost:61616/exampleTopic];containerRelativeID=0];containerID=JMSID[tcp://localhost:61616/exampleTopic];serviceid=0;serviceranking=0;classes=[org.eclipse.ecf.examples.loadbalancing.IDataProcessor];state=0;properties={ecf.rsvc.id=0, jms.queue.loadbalance=true}]]
	input data=Are we not drawn onward, we few, drawn onward to new era 
	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(Vf/B9giiOv3dCEQrAVKPrREJgBY=).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