Failover and Load Distributor Feature

Failover

The CXF Failover feature allows to configure CXF frontend clients to retry a call when the target endpoint becomes unavailable.
A number of retry strategies available: a client can iterate sequentially over the alternative addresses or chose them randomly.
Every strategy can be configured to do a delay between selecting the addresses.

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:clustering="http://cxf.apache.org/clustering"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/clustering http://cxf.apache.org/schemas/clustering.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
    
    <util:list id="addressList">
        <value>http://localhost:${testutil.ports.Server.1}/services1</value>
        <value>http://localhost:${testutil.ports.Server.2}/services2</value>
        <value>http://localhost:${testutil.ports.Server.3}/services3</value>
    </util:list>

    <bean id="SequentialAddresses" class="org.apache.cxf.clustering.SequentialStrategy">
        <property name="alternateAddresses">
            <ref bean="addressList"/>
        </property>
        <!-- delay a retry for 1/10 of a second -->
        <property name="delayBetweenRetries" value="100"/>
    </bean>

    <bean id="RandomAddresses" class="org.apache.cxf.clustering.RandomStrategy">
        <property name="alternateAddresses">
            <ref bean="addressList"/>
        </property>
    </bean>

    <!-- other jaxws:client attributes and elements are omitted for brevity -->
    
    <jaxws:client id="clientWithSeqFailoverSupport" address="http://localhost:8080/services">
       <jaxws:features>
           <clustering:failover>
                <clustering:strategy>
                    <ref bean="SequentialAddresses"/>
                </clustering:strategy>
            </clustering:failover>
       </jaxws:features>
    </jaxws:client>

    <!-- other jaxws:client attributes and elements are omitted for brevity -->

    <jaxws:client id="clientWithRandomFailoverSupport" address="http://localhost:8080/initialAddress">
       <jaxws:features>
           <clustering:failover>
                <clustering:strategy>
                    <ref bean="RandomAddresses"/>
                </clustering:strategy>
            </clustering:failover>
       </jaxws:features>
    </jaxws:client>

</beans>

Note, org.apache.cxf.clustering.RetryStrategy can be used to retry the same, last address for a limited number of times, before switching to the next address. Use RetryStrategy 'maxNumberOfRetries' property. RetryStrategy currently uses a sequential algorithm for selecting the addresses.

Circuit Breakers Failover

The recent addition to CXF failover features is the implementation based on circuit breakers, more precisely Apache Zest (https://zest.apache.org/) library. The configuration is very similar to the regular failover strategy, the only difference is usage of clustering:circuit-breaker-failover element.

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:clustering="http://cxf.apache.org/clustering"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/clustering http://cxf.apache.org/schemas/clustering.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
    
    <util:list id="addressList">
        <value>http://localhost:${testutil.ports.Server.1}/services1</value>
        <value>http://localhost:${testutil.ports.Server.2}/services2</value>
        <value>http://localhost:${testutil.ports.Server.3}/services3</value>
    </util:list>

    <bean id="SequentialAddresses" class="org.apache.cxf.clustering.SequentialStrategy">
        <property name="alternateAddresses">
            <ref bean="addressList"/>
        </property>
        <!-- delay a retry for 1/10 of a second -->
        <property name="delayBetweenRetries" value="100"/>
    </bean>

    <bean id="RandomAddresses" class="org.apache.cxf.clustering.RandomStrategy">
        <property name="alternateAddresses">
            <ref bean="addressList"/>
        </property>
    </bean>

    <!-- other jaxws:client attributes and elements are omitted for brevity -->
    
    <jaxws:client id="clientWithSeqFailoverSupport" address="http://localhost:8080/services">
       <jaxws:features>
           <clustering:circuit-breaker-failover threshold="1" timeout="60000">
               <clustering:strategy>                   
                   <ref bean="SequentialAddresses"/>
               </clustering:strategy>
            </clustering:circuit-breaker-failover>
       </jaxws:features>
    </jaxws:client>

    <!-- other jaxws:client attributes and elements are omitted for brevity -->

    <jaxws:client id="clientWithRandomFailoverSupport" address="http://localhost:8080/initialAddress">
       <jaxws:features>
           <clustering:circuit-breaker-failover threshold="1" timeout="60000">
                <clustering:strategy>
                    <ref bean="RandomAddresses"/>
                </clustering:strategy>
            </clustering:circuit-breaker-failover>
       </jaxws:features>
    </jaxws:client>

</beans>

Circuit breakers have recommended themselves as a proven strategy to handle and monitor the failures related to external service calls, giving the external systems a time to recover by preventing endless retries or time-outing. For that reason, two configuration parameters could be tuned:

  • threshold: the error threshold to open the circuit breaker
  • timeout: the timeout to wait before trying the next invocation

Load Distribution

Load Distributor Feature is a Failover feature which can allow the clients to iterate over alternative addresses on every new call, irrespectively of whether the last call has reached its target or not. It can help with the controlling the traffic originating from CXF clients at individual servers.

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:clustering="http://cxf.apache.org/clustering"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/clustering http://cxf.apache.org/schemas/clustering.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>     

    <util:list id="addressList">
        <value>http://localhost:${testutil.ports.Server.1}/services1</value>
        <value>http://localhost:${testutil.ports.Server.2}/services2</value>
        <value>http://localhost:${testutil.ports.Server.3}/services3</value>
    </util:list>

    <bean id="SequentialAddresses" class="org.apache.cxf.clustering.SequentialStrategy">
        <property name="alternateAddresses">
            <ref bean="addressList"/>
        </property>
    </bean>

    <!-- other jaxws:client attributes and elements are omitted for brevity -->
    
    <jaxws:client id="clientWithLoadDistributor" address="http://localhost:8080/services">
       <jaxws:features>
           <clustering:loadDistributor>
                <clustering:strategy>
                    <ref bean="SequentialAddresses"/>
                </clustering:strategy>
            </clustering:loadDistributor>
       </jaxws:features>
    </jaxws:client>
</beans>

Configuring JAX-RS clients

JAX-RS clients are configured exactly as JAX-WS clients are, please see this page for more info.