You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@synapse.apache.org by ru...@apache.org on 2008/06/24 06:53:00 UTC

svn commit: r671024 - in /synapse/trunk/java: modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/ modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/utils/ modules/core/src/main/java/org/apache/synapse/endpoints/ modules...

Author: ruwan
Date: Mon Jun 23 21:53:00 2008
New Revision: 671024

URL: http://svn.apache.org/viewvc?rev=671024&view=rev
Log:
Committing for azeez, (SYNAPSE-372)

Added:
    synapse/trunk/java/repository/conf/sample/synapse_sample_58.xml
Modified:
    synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/LoadbalanceEndpointFactory.java
    synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/utils/LoadbalanceAlgorithmFactory.java
    synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/LoadbalanceEndpoint.java
    synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/algorithms/RoundRobin.java
    synapse/trunk/java/src/site/xdoc/Synapse_Samples.xml

Modified: synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/LoadbalanceEndpointFactory.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/LoadbalanceEndpointFactory.java?rev=671024&r1=671023&r2=671024&view=diff
==============================================================================
--- synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/LoadbalanceEndpointFactory.java (original)
+++ synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/LoadbalanceEndpointFactory.java Mon Jun 23 21:53:00 2008
@@ -21,29 +21,36 @@
 
 import org.apache.axiom.om.OMAttribute;
 import org.apache.axiom.om.OMElement;
+import org.apache.axis2.clustering.Member;
 import org.apache.synapse.SynapseConstants;
 import org.apache.synapse.config.xml.endpoints.utils.LoadbalanceAlgorithmFactory;
+import org.apache.synapse.config.xml.XMLConfigConstants;
 import org.apache.synapse.endpoints.Endpoint;
 import org.apache.synapse.endpoints.LoadbalanceEndpoint;
 import org.apache.synapse.endpoints.algorithms.LoadbalanceAlgorithm;
 
 import javax.xml.namespace.QName;
 import java.util.ArrayList;
+import java.util.List;
+import java.util.Iterator;
 
 /**
  * Creates {@link LoadbalanceEndpoint} using an XML configuration.
- *
+ * <p/>
  * &lt;endpoint [name="name"]&gt;
- *    &lt;loadbalance policy="load balance algorithm"&gt;
- *       &lt;endpoint&gt;+
- *    &lt;/loadbalance&gt;
+ * &lt;loadbalance policy="load balance algorithm"&gt;
+ * &lt;endpoint&gt;+
+ * &lt;/loadbalance&gt;
  * &lt;/endpoint&gt;
  */
 public class LoadbalanceEndpointFactory extends EndpointFactory {
 
     private static LoadbalanceEndpointFactory instance = new LoadbalanceEndpointFactory();
+    private static final QName MEMBER = new QName(SynapseConstants.SYNAPSE_NAMESPACE,
+                                    "member");
 
-    private LoadbalanceEndpointFactory() {}
+    private LoadbalanceEndpointFactory() {
+    }
 
     public static LoadbalanceEndpointFactory getInstance() {
         return instance;
@@ -56,7 +63,7 @@
         OMElement loadbalanceElement = epConfig.getFirstChildWithName(
                 new QName(SynapseConstants.SYNAPSE_NAMESPACE, "loadbalance"));
 
-        if(loadbalanceElement != null) {
+        if (loadbalanceElement != null) {
 
             LoadbalanceEndpoint loadbalanceEndpoint = new LoadbalanceEndpoint();
 
@@ -68,13 +75,26 @@
                 loadbalanceEndpoint.setName(name.getAttributeValue());
             }
 
-            // set endpoints
-            ArrayList<Endpoint> endpoints = getEndpoints(loadbalanceElement, loadbalanceEndpoint);
-            loadbalanceEndpoint.setEndpoints(endpoints);
+            LoadbalanceAlgorithm algorithm = null;
+
+            // set endpoints or members
+            if (loadbalanceElement.getFirstChildWithName(XMLConfigConstants.ENDPOINT_ELT) != null) {
+                ArrayList<Endpoint> endpoints
+                        = getEndpoints(loadbalanceElement, loadbalanceEndpoint);
+                loadbalanceEndpoint.setEndpoints(endpoints);
+                algorithm =
+                        LoadbalanceAlgorithmFactory.
+                                createLoadbalanceAlgorithm(loadbalanceElement, endpoints);
+            } else if (loadbalanceElement.getFirstChildWithName(MEMBER) != null) {
+                List<Member> members = getMembers(loadbalanceElement);
+                loadbalanceEndpoint.setMembers(members);
+                algorithm =
+                        LoadbalanceAlgorithmFactory.
+                                createLoadbalanceAlgorithm2(loadbalanceElement, members);
+                loadbalanceEndpoint.startApplicationMembershipTimer();
+            }
 
             // set load balance algorithm
-            LoadbalanceAlgorithm algorithm = LoadbalanceAlgorithmFactory.
-                    createLoadbalanceAlgorithm(loadbalanceElement, endpoints);
             loadbalanceEndpoint.setAlgorithm(algorithm);
 
             // set if failover is turned off
@@ -88,4 +108,23 @@
 
         return null;  //To change body of implemented methods use File | Settings | File Templates.
     }
+
+    private List<Member> getMembers(OMElement loadbalanceElement) {
+        List<Member> members = new ArrayList<Member>();
+        for(Iterator memberIter = loadbalanceElement.getChildrenWithName(MEMBER);
+            memberIter.hasNext();){
+            OMElement memberEle = (OMElement) memberIter.next();
+            Member member = new Member(memberEle.getAttributeValue(new QName("ip")), -1);
+            String http = memberEle.getAttributeValue(new QName("httpPort"));
+            if (http != null) {
+                member.setHttpPort(Integer.parseInt(http));
+            }
+            String https = memberEle.getAttributeValue(new QName("httpsPort"));
+            if (https != null && https.trim().length() != 0) {
+                member.setHttpsPort(Integer.parseInt(https.trim()));
+            }
+            members.add(member);
+        }
+        return members;
+    }
 }

Modified: synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/utils/LoadbalanceAlgorithmFactory.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/utils/LoadbalanceAlgorithmFactory.java?rev=671024&r1=671023&r2=671024&view=diff
==============================================================================
--- synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/utils/LoadbalanceAlgorithmFactory.java (original)
+++ synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/utils/LoadbalanceAlgorithmFactory.java Mon Jun 23 21:53:00 2008
@@ -19,14 +19,16 @@
 
 package org.apache.synapse.config.xml.endpoints.utils;
 
-import org.apache.axiom.om.OMElement;
 import org.apache.axiom.om.OMAttribute;
+import org.apache.axiom.om.OMElement;
+import org.apache.axis2.clustering.Member;
+import org.apache.synapse.config.xml.XMLConfigConstants;
 import org.apache.synapse.endpoints.algorithms.LoadbalanceAlgorithm;
 import org.apache.synapse.endpoints.algorithms.RoundRobin;
-import org.apache.synapse.config.xml.XMLConfigConstants;
 
 import javax.xml.namespace.QName;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Factory of all load balance algorithms. ESBSendMediatorFactroy will use this to create the
@@ -35,19 +37,37 @@
 public class LoadbalanceAlgorithmFactory {
 
     public static LoadbalanceAlgorithm createLoadbalanceAlgorithm(OMElement loadbalanceElement,
-        ArrayList endpoints) {
+                                                                  ArrayList endpoints) {
+        LoadbalanceAlgorithm algorithm = null;
+        String algorithmName = "roundRobin";
+        OMAttribute algoAttribute =
+                loadbalanceElement.getAttribute(new QName(null, XMLConfigConstants.ALGORITHM_NAME));
+        if(algoAttribute != null) {
+            algorithmName = algoAttribute.getAttributeValue();
+        }
+
+        if (algorithmName.equalsIgnoreCase("roundRobin")) {
+            algorithm = new RoundRobin(endpoints);
+        }
+
+        return algorithm;
+    }
+
+    public static LoadbalanceAlgorithm createLoadbalanceAlgorithm2(OMElement loadbalanceElement,
+                                                                   List<Member> members) {
 
         LoadbalanceAlgorithm algorithm = null;
 
         String algorithmName = "roundRobin";
-        OMAttribute algoAttribute = loadbalanceElement.getAttribute(new QName(
-                null, XMLConfigConstants.ALGORITHM_NAME));
-        if(algoAttribute != null) {
+        OMAttribute algoAttribute =
+                loadbalanceElement.getAttribute(new QName(null, XMLConfigConstants.ALGORITHM_NAME));
+        if (algoAttribute != null) {
             algorithmName = algoAttribute.getAttributeValue();
         }
 
-        if(algorithmName.equalsIgnoreCase("roundRobin")) {
-                algorithm = new RoundRobin(endpoints);
+        if (algorithmName.equalsIgnoreCase("roundRobin")) {
+            algorithm = new RoundRobin();
+            algorithm.setApplicationMembers(members);
         }
 
         return algorithm;

Modified: synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/LoadbalanceEndpoint.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/LoadbalanceEndpoint.java?rev=671024&r1=671023&r2=671024&view=diff
==============================================================================
--- synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/LoadbalanceEndpoint.java (original)
+++ synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/LoadbalanceEndpoint.java Mon Jun 23 21:53:00 2008
@@ -19,18 +19,32 @@
 
 package org.apache.synapse.endpoints;
 
+import org.apache.axis2.addressing.EndpointReference;
 import org.apache.axis2.clustering.ClusterManager;
+import org.apache.axis2.clustering.Member;
 import org.apache.axis2.context.ConfigurationContext;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.synapse.FaultHandler;
 import org.apache.synapse.MessageContext;
 import org.apache.synapse.SynapseConstants;
+import org.apache.synapse.SynapseException;
 import org.apache.synapse.core.axis2.Axis2MessageContext;
 import org.apache.synapse.endpoints.algorithms.AlgorithmContext;
 import org.apache.synapse.endpoints.algorithms.LoadbalanceAlgorithm;
+import org.apache.synapse.endpoints.utils.EndpointDefinition;
 
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.InetAddress;
+import java.net.SocketAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
 import java.util.List;
+import java.util.TimerTask;
+import java.util.Timer;
+import java.util.ArrayList;
+import java.io.IOException;
 
 /**
  * Load balance endpoint can have multiple endpoints. It will route messages according to the
@@ -57,6 +71,16 @@
     private List<Endpoint> endpoints = null;
 
     /**
+     * List of currently available application members amongst which the load is distributed
+     */
+    private List<Member> activeMembers = null;
+
+    /**
+     * List of currently unavailable members
+     */
+    private List<Member> inactiveMembers = null;
+
+    /**
      * Algorithm used for selecting the next endpoint to direct the load. Default is RoundRobin.
      */
     private LoadbalanceAlgorithm algorithm = null;
@@ -84,6 +108,11 @@
      */
     private final AlgorithmContext algorithmContext = new AlgorithmContext();
 
+    public void startApplicationMembershipTimer(){
+        Timer timer = new Timer();
+        timer.scheduleAtFixedRate(new MemberActivatorTask(), 1000, 500);
+    }
+
     public void send(MessageContext synMessageContext) {
 
         if (log.isDebugEnabled()) {
@@ -131,6 +160,19 @@
             }
         }
 
+        if (endpoints != null) {
+            sendToEndpoint(synMessageContext);
+        } else if (activeMembers != null) {
+            EndpointReference to = synMessageContext.getTo();
+            LoadbalanceFaultHandler faultHandler = new LoadbalanceFaultHandler(to);
+            if (failover) {
+                synMessageContext.pushFaultHandler(faultHandler);
+            }
+            sendToApplicationMember(synMessageContext, to, faultHandler);
+        }
+    }
+
+    private void sendToEndpoint(MessageContext synMessageContext) {
         Endpoint endpoint = algorithm.getNextEndpoint(synMessageContext, algorithmContext);
         if (endpoint != null) {
 
@@ -158,6 +200,54 @@
         }
     }
 
+    private void sendToApplicationMember(MessageContext synCtx,
+                                         EndpointReference to,
+                                         LoadbalanceFaultHandler faultHandler) {
+        org.apache.axis2.context.MessageContext axis2MsgCtx =
+                ((Axis2MessageContext) synCtx).getAxis2MessageContext();
+
+        String transport = axis2MsgCtx.getTransportIn().getName();
+        algorithm.setApplicationMembers(activeMembers);
+        Member currentMember = algorithm.getNextApplicationMember(algorithmContext);
+        faultHandler.setCurrentMember(currentMember);
+
+        if (currentMember != null) {
+
+            // URL rewrite
+            if (transport.equals("http") || transport.equals("https")) {
+                String address = to.getAddress();
+                if (address.indexOf(":") != -1) {
+                    try {
+                        address = new URL(address).getPath();
+                    } catch (MalformedURLException e) {
+                        String msg = "URL " + address + " is malformed";
+                        log.error(msg, e);
+                        throw new SynapseException(msg, e);
+                    }
+                }
+                EndpointReference epr =
+                        new EndpointReference(transport + "://" + currentMember.getHostName() +
+                                              ":" + currentMember.getHttpPort() + address);
+                synCtx.setTo(epr);
+                if (failover) {
+                    synCtx.getEnvelope().build();
+                }
+
+                AddressEndpoint endpoint = new AddressEndpoint();
+                EndpointDefinition definition = new EndpointDefinition();
+                endpoint.setEndpoint(definition);
+                endpoint.send(synCtx);
+            } else {
+                log.error("Cannot load balance for non-HTTP/S transport " + transport);
+            }
+        } else {
+            synCtx.getFaultStack().pop(); // Remove the LoadbalanceFaultHandler
+            String msg = "No application members available";
+            log.error(msg);
+            throw new SynapseException(msg);
+        }
+    }
+
     public String getName() {
         return name;
     }
@@ -174,6 +264,11 @@
         this.algorithm = algorithm;
     }
 
+    public void setMembers(List<Member> members) {
+        this.activeMembers = members;
+        this.inactiveMembers = new ArrayList<Member>();
+    }
+
     /**
      * If this endpoint is in inactive state, checks if all immediate child endpoints are still
      * failed. If so returns false. If at least one child endpoint is in active state, sets this
@@ -246,4 +341,95 @@
             }
         }
     }
+
+    /**
+     * This FaultHandler will try to resend the message to another member if an error occurs
+     * while sending to some member. This is a failover mechanism
+     */
+    private class LoadbalanceFaultHandler extends FaultHandler {
+
+        private EndpointReference to;
+        private Member currentMember;
+
+        public void setCurrentMember(Member currentMember) {
+            this.currentMember = currentMember;
+        }
+
+        private LoadbalanceFaultHandler(EndpointReference to) {
+            this.to = to;
+        }
+
+        public void onFault(MessageContext synCtx) {
+            if (currentMember == null) {
+                return;
+            }
+            synCtx.pushFaultHandler(this);
+            activeMembers.remove(currentMember); // This member has to be inactivated
+            inactiveMembers.add(currentMember);
+            sendToApplicationMember(synCtx, to, this);
+        }
+    }
+
+    /**
+     * The task which checks whther inactive members have become available again 
+     */
+    private class MemberActivatorTask extends TimerTask{
+
+        public void run() {
+            try {
+                for(Member member: inactiveMembers){
+                    if(canConnect(member)){
+                        inactiveMembers.remove(member);
+                        activeMembers.add(member);
+                    }
+                }
+            } catch (Exception ignored) {
+                // Ignore all exceptions. The timer should continue to run
+            }
+        }
+
+        /**
+         * Before activating a member, we will try to verify whether we can connect to it
+         *
+         * @param member The member whose connectvity needs to be verified
+         * @return true, if the member can be contacted; false, otherwise.
+         */
+        private boolean canConnect(Member member) {
+            if(log.isDebugEnabled()){
+                log.debug("Trying to connect to member " + member.getHostName() + "...");
+            }
+            for (int retries = 30; retries > 0; retries--) {
+                try {
+                    InetAddress addr = InetAddress.getByName(member.getHostName());
+                    int httpPort = member.getHttpPort();
+                    if(log.isDebugEnabled()){
+                        log.debug("HTTP Port=" + httpPort);
+                    }
+                    if (httpPort != -1) {
+                        SocketAddress httpSockaddr = new InetSocketAddress(addr, httpPort);
+                        new Socket().connect(httpSockaddr, 10000);
+                    }
+                    int httpsPort = member.getHttpsPort();
+                    if(log.isDebugEnabled()){
+                        log.debug("HTTPS Port=" + httpPort);
+                    }
+                    if (httpsPort != -1) {
+                        SocketAddress httpsSockaddr = new InetSocketAddress(addr, httpsPort);
+                        new Socket().connect(httpsSockaddr, 10000);
+                    }
+                    return true;
+                } catch (IOException e) {
+                    if(log.isDebugEnabled()){
+                        log.debug("", e);
+                    }
+                    String msg = e.getMessage();
+                    if (msg.indexOf("Connection refused") == -1 &&
+                        msg.indexOf("connect timed out") == -1) {
+                        log.error("Cannot connect to member " + member, e);
+                    }
+                }
+            }
+            return false;
+        }
+    }
 }

Modified: synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/algorithms/RoundRobin.java
URL: http://svn.apache.org/viewvc/synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/algorithms/RoundRobin.java?rev=671024&r1=671023&r2=671024&view=diff
==============================================================================
--- synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/algorithms/RoundRobin.java (original)
+++ synapse/trunk/java/modules/core/src/main/java/org/apache/synapse/endpoints/algorithms/RoundRobin.java Mon Jun 23 21:53:00 2008
@@ -41,12 +41,18 @@
      */
     private ArrayList endpoints = null;
 
+    /**
+     * List of application members in the loadb balance group
+     */
     private List<Member> members;
 
     public RoundRobin(ArrayList endpoints) {
         this.endpoints = endpoints;
     }
 
+    public RoundRobin() {
+    }
+
     public void setApplicationMembers(List<Member> members) {
         this.members = members;
     }
@@ -56,7 +62,7 @@
      * available, returns null.
      *
      * @param synapseMessageContext MessageContext instance which holds all per-message properties
-     * @param algorithmContext      The context in which holds run time states related to the algorithm
+     * @param algorithmContext The context in which holds run time states related to the algorithm
      * @return endpoint to send the next message
      */
     public Endpoint getNextEndpoint(MessageContext synapseMessageContext,

Added: synapse/trunk/java/repository/conf/sample/synapse_sample_58.xml
URL: http://svn.apache.org/viewvc/synapse/trunk/java/repository/conf/sample/synapse_sample_58.xml?rev=671024&view=auto
==============================================================================
--- synapse/trunk/java/repository/conf/sample/synapse_sample_58.xml (added)
+++ synapse/trunk/java/repository/conf/sample/synapse_sample_58.xml Mon Jun 23 21:53:00 2008
@@ -0,0 +1,56 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you under the Apache License, Version 2.0 (the
+  ~  "License"); you may not use this file except in compliance
+  ~  with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing,
+  ~  software distributed under the License is distributed on an
+  ~   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~  KIND, either express or implied.  See the License for the
+  ~  specific language governing permissions and limitations
+  ~  under the License.
+  -->
+
+<!-- Session less load balancing between 3 endpoints -->
+<definitions xmlns="http://ws.apache.org/ns/synapse">
+
+    <sequence name="main" onError="errorHandler">
+        <in>
+            <send>
+                <endpoint>
+                    <loadbalance failover="true">
+                        <member ip="127.0.0.1" httpPort="9001" httpsPort="9005"/>
+                        <member ip="127.0.0.1" httpPort="9002" httpsPort="9006"/>
+                        <member ip="127.0.0.1" httpPort="9003" httpsPort="9007"/>
+                    </loadbalance>
+                </endpoint>
+            </send>
+            <drop/>
+        </in>
+
+        <out>
+            <!-- Send the messages where they have been sent (i.e. implicit To EPR) -->
+            <send/>
+        </out>
+    </sequence>
+
+    <sequence name="errorHandler">
+
+        <makefault>
+            <code value="tns:Receiver" xmlns:tns="http://www.w3.org/2003/05/soap-envelope"/>
+            <reason value="COULDN'T SEND THE MESSAGE TO THE SERVER."/>
+        </makefault>
+
+        <header name="To" action="remove"/>
+        <property name="RESPONSE" value="true"/>
+
+        <send/>
+    </sequence>
+
+</definitions>

Modified: synapse/trunk/java/src/site/xdoc/Synapse_Samples.xml
URL: http://svn.apache.org/viewvc/synapse/trunk/java/src/site/xdoc/Synapse_Samples.xml?rev=671024&r1=671023&r2=671024&view=diff
==============================================================================
--- synapse/trunk/java/src/site/xdoc/Synapse_Samples.xml (original)
+++ synapse/trunk/java/src/site/xdoc/Synapse_Samples.xml Mon Jun 23 21:53:00 2008
@@ -218,6 +218,10 @@
               <a href="#Sample57">Sample 57: Dynamic load balancing
               between 3 nodes</a>
             </li>
+              <li>
+              <a href="#Sample58">Sample 58: Static load balancing
+              between 3 nodes</a>
+            </li>
           </ul>
         </li>
         <li>
@@ -2164,6 +2168,119 @@
       all three servers.
     </p>
 
+<h2>
+      <a name="Sample58" id="Sample58">Sample 58: Static load balancing between 3 nodes</a>
+    </h2>
+<pre xml:space="preserve">
+
+&lt;definitions xmlns="http://ws.apache.org/ns/synapse"&gt;
+
+    &lt;sequence name="main" onError="errorHandler"&gt;
+        &lt;in&gt;
+            &lt;send&gt;
+                &lt;endpoint&gt;
+                    &lt;loadbalance failover="true"&gt;
+                        &lt;member ip="127.0.0.1" httpPort="9001" httpsPort="9005"/&gt;
+                        &lt;member ip="127.0.0.1" httpPort="9002" httpsPort="9006"/&gt;
+                        &lt;member ip="127.0.0.1" httpPort="9003" httpsPort="9007"/&gt;
+                    &lt;/loadbalance&gt;
+                &lt;/endpoint&gt;
+            &lt;/send&gt;
+            &lt;drop/&gt;
+        &lt;/in&gt;
+
+        &lt;out&gt;
+            &lt;send/&gt;
+        &lt;/out&gt;
+    &lt;/sequence&gt;
+
+    &lt;sequence name="errorHandler"&gt;
+
+        &lt;makefault&gt;
+            &lt;code value="tns:Receiver" xmlns:tns="http://www.w3.org/2003/05/soap-envelope"/&gt;
+            &lt;reason value="COULDN'T SEND THE MESSAGE TO THE SERVER."/&gt;
+        &lt;/makefault&gt;
+
+        &lt;header name="To" action="remove"/&gt;
+        &lt;property name="RESPONSE" value="true"/&gt;
+
+        &lt;send/&gt;
+    &lt;/sequence&gt;
+
+&lt;/definitions&gt;
+
+</pre>
+    <p>
+      <strong>Objective: Demonstrate the simple static load balancing among a set of
+      nodes</strong>
+    </p>
+    <p>
+      <strong>Prerequisites:</strong>
+    </p>
+    <p>
+      Start Synapse with sample configuration 58. (i.e. synapse -sample 58)
+    </p>
+    <p>
+      Deploy the LoadbalanceFailoverService by switching to &lt;Synapse
+      installation directory&gt;/samples/axis2Server/src/LoadbalanceFailoverService
+      directory and running ant.
+    </p>
+    <p>
+      Start three instances of sample Axis2 server on HTTP ports 9001, 9002 and
+      9003 and give some unique names to each server.
+    </p>
+    <p>
+      Example commands to run sample Axis2 servers from the &lt;Synapse
+      installation directory&gt;/samples/axis2Server directory in Linux are
+      listed below:
+    </p>
+<pre xml:space="preserve">./axis2server.sh -http 9001 -https 9005 -name MyServer1
+./axis2server.sh -http 9002 -https 9006 -name MyServer2
+./axis2server.sh -http 9003 -https 9007 -name MyServer3</pre>
+    <p>
+      Now we are done with setting up the environment for load balance sample.
+      Start the load balance and failover client using the following command:
+    </p>
+<pre xml:space="preserve">ant loadbalancefailover -Di=100</pre>
+    <p>
+      This client sends 100 requests to the LoadbalanceFailoverService through
+      Synapse. Synapse will distribute the load among the three nodes
+      mentioned in the configuration in a round-robin manner.
+      LoadbalanceFailoverService appends the name of the server to the response,
+      so that client can determine which server has processed the message. If
+      you examine the console output of the client, you can see that requests
+      are processed by three servers as follows:
+    </p>
+<pre xml:space="preserve">[java] Request: 1 ==&gt; Response from server: MyServer1
+[java] Request: 2 ==&gt; Response from server: MyServer2
+[java] Request: 3 ==&gt; Response from server: MyServer3
+[java] Request: 4 ==&gt; Response from server: MyServer1
+[java] Request: 5 ==&gt; Response from server: MyServer2
+[java] Request: 6 ==&gt; Response from server: MyServer3
+[java] Request: 7 ==&gt; Response from server: MyServer1
+...</pre>
+    <p>
+      Now run the client without the -Di=100 parameter, i.e. ant loadbalancefailover,
+      to send infinite requests. While running the client shutdown the server named MyServer1.
+      You can observe that requests are only distributed among MyServer2 and
+      MyServer3 after shutting down MyServer1. Console output before and after
+      shutting down MyServer1 is listed below (MyServer1 was shutdown after
+      request 63):
+    </p>
+<pre xml:space="preserve">...
+[java] Request: 61 ==&gt; Response from server: MyServer1
+[java] Request: 62 ==&gt; Response from server: MyServer2
+[java] Request: 63 ==&gt; Response from server: MyServer3
+[java] Request: 64 ==&gt; Response from server: MyServer2
+[java] Request: 65 ==&gt; Response from server: MyServer3
+[java] Request: 66 ==&gt; Response from server: MyServer2
+[java] Request: 67 ==&gt; Response from server: MyServer3
+...</pre>
+    <p>
+      Now restart MyServer1. You can observe that requests will be again sent to
+      all three servers.
+    </p>
+
     <h1>
       <a name="MessageMediationQoS" id="MessageMediationQoS">Quality of
       Service addition or deduction samples in message mediation</a>