CXF鏄竴涓瘮杈冩祦琛岀殑Web Service妗嗘灦. ( 褰撶劧濡傛灉榪芥眰鏇撮珮鏁? 榪樺彲浠ュ幓鎼滅儲(chǔ)ice, thrift, protobuff涔嬬被鐨?
榪戜竴涓湀, 鏂柇緇畫鍦板張濂藉ソ鐪嬩簡(jiǎn)鐪婥XF鐨勪竴浜涗唬鐮? CXF鐨勬枃妗h繕鏄緢嬈犵己,鐗瑰埆鏄叧浜庡唴閮ㄥ疄鐜扮殑涓滆タ. 浠庢垜鐨勬劅瑙夋潵璇? 鍐呴儴瀹炵幇榪樻槸鎸哄鏉傜殑. Inteceptor, Feature, ConduitSelector 榪欎簺姒傚康涓澶у爢, 鍙堝樊涓嶅鍙互鍋氱被浼肩殑浜嬫儏, 鐪熸槸璁╀漢澶存檿.
CXF鏈韓鎻愪緵浜?jiǎn)涓涓狥ailoverFeature, 鍙互鍦ㄨ皟鐢ㄦ湇鍔″嚭閿欐椂鍒囨崲鍒板叾浠栨湇鍔″櫒, 浣嗘槸鏃犳硶鍋氬埌璐熻澆鍧囪 , 鎴戠爺絀朵簡(jiǎn)鍑犲ぉ, 鍦‵ailoverFeature鐨勫熀紜涓婃敼鍑烘潵涓涓狶oadBalanceFeature, 褰撶劧涔熷悓鏃舵敮鎸丗ailover.
棣栧厛鎴戜滑鏉ョ湅鐪嬪浣曚嬌鐢–XF鐨凢ailoverFeature: (涓嬭澆紺轟緥涓寘鎷嬌鐢▁ml鍜屼唬鐮佷袱縐嶆柟寮? 褰撶劧CXF鑷繁榪樻彁渚涗簡(jiǎn)浣跨敤wsdl鍐呴儴瀹氫箟鐨勬柟寮?
鎴戜滑闇瑕佸厛鍑嗗涓涓狧elloService, 闈炲父綆鍗曠殑涓涓猈eb Service, 榪欓噷涓嶅湪璐村嚭, 鍏蜂綋鍙互鐪嬩笅杞藉寘
璋冪敤浠g爜紺轟緥:
package org.javascud.extensions.cxf.testfailover;
import org.apache.cxf.clustering.FailoverFeature;
import org.apache.cxf.clustering.RandomStrategy;
import org.apache.cxf.feature.AbstractFeature;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.javascud.extensions.cxf.service.Hello;
import java.util.ArrayList;
import java.util.List;
public class HelloServiceFailOverClient
{
public static void main(String[] args)
{
String helloFirst = "http://localhost:8080/service/Hello";
String helloSecond = "http://localhost:8081/service/Hello";
String helloThird = "http://localhost:8082/service/Hello";
String helloFour = "http://localhost:8083/service/Hello";
List<String> serviceList = new ArrayList<String>();
serviceList.add(helloFirst);
serviceList.add(helloSecond);
serviceList.add(helloThird);
//serviceList.add(helloFour);
RandomStrategy strategy = new RandomStrategy();
strategy.setAlternateAddresses(serviceList);
FailoverFeature ff = new FailoverFeature();
ff.setStrategy(strategy);
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
List<AbstractFeature> features = new ArrayList<AbstractFeature>();
features.add(ff);
factory.setFeatures(features);
factory.initFeatures();
factory.setServiceClass(Hello.class);
//factory.setAddress("http://localhost:8080/service/Hello");
Hello client = (Hello) factory.create();
String result = client.sayHello("felix");
System.out.println("result is: " + result);
}
}
鍦ㄩ亣鍒伴敊璇椂鍙互鑷姩浣跨敤涓嬩竴涓湇鍔″櫒, 浣嗘槸蹇呴』瑕佽嚜宸辮緗竴涓湴鍧, 濡傛灉涓嶈緗殑璇濅篃鍙互, 浣嗘槸浼?xì)鍑洪敊鐒跺悗failover.
涓嬮潰鎴戜滑鑷繁鏉ョ湅鐪嬫垜浠殑 LoadBalanceFeature
1. 棣栧厛鎴戜滑鍒涘緩涓涓狶oadBalanceFeature (瀹屽叏鍜孎ailoverFeature涓鏍?
Feature鏄敤鏉ュ畾鍒禨erver, Client, Bus鐨勪竴涓粍浠? 鍏蜂綋鍙互鏌ョ湅AbstractFeature, 鎴戜滑浣跨敤initialize鏂規(guī)硶鏉ュ畾鍒禖lient, 淇敼Client鐨凜onduit閫夋嫨鍣ㄨ揪鍒拌礋杞藉潎琛$殑鐩殑.
LoadBalanceFeature浠g爜濡備笅:
/**
* This feature may be applied to a Client so as to enable
* load balance , use any compatible endpoint for the target service.
*
* @author Felix Zhang Date:2010-10-3 22:58
* @see org.apache.cxf.clustering.FailoverFeature
*/
public class LoadBalanceFeature extends AbstractFeature {
private LoadBalanceStrategy loadBalanceStrategy;
@Override
public void initialize(Client client, Bus bus) {
LoadBalanceTargetSelector selector = new LoadBalanceTargetSelector();
selector.setEndpoint(client.getEndpoint());
selector.setStrategy(getStrategy());
client.setConduitSelector(selector);
}
public void setStrategy(LoadBalanceStrategy strategy) {
loadBalanceStrategy = strategy;
}
public LoadBalanceStrategy getStrategy() {
return loadBalanceStrategy;
}
}
2. 瀹氬埗涓涓狶oadBalanceStrategy 璐熻澆鍧囪 絳栫暐
璐熻澆鍧囪 絳栫暐鏈夊緢澶氱, 渚嬪闅忔満閫夋嫨, 欏哄簭閫夋嫨絳? FailoverFeature鎻愪緵浜?jiǎn)涓壙U嶇瓥鐣? 鎬諱箣寰堢畝鍗? 鎴戜滑鍦ㄨ繖閲屽氨鍏堝疄鐜伴殢鏈虹瓥鐣? 鍏朵粬鐨勭瓥鐣ラ兘寰堢畝鍗? 鍑犺浠g爜灝卞彲浠ュ疄鐜頒簡(jiǎn).
榪欎釜綾諱富瑕佺敤鏉ヨ緗?鑾峰彇鎵鏈夌殑鎻愪緵鏈嶅姟鐨勫湴鍧鍒楄〃, 涓轟簡(jiǎn)鏂逛究鎺у埗, 鎴戞柊澧炰簡(jiǎn)2涓夐」:
A: alwaysChangeEndpoint 鏄惁姣忔璇鋒眰閮藉垏鎹㈠湴鍧:銆濡傛灉鍙湁涓涓鎴風(fēng), 鍙互鍒嗘媴璐熻澆. 緙虹渷涓簍rue
B: removeFailedEndpoint 鏄惁浠庡叏灞鐨勫湴鍧鍒楄〃涓Щ闄ゅけ璐ユ湇鍔″湴鍧 -- 濡傛灉浣犳病鏈夌洃嫻嬫湇鍔″櫒鐘舵佺殑紼嬪簭
鍏充簬鍔ㄦ佸鍒犳湇鍔″湴鍧
- 鍙互浣跨敤zookeeper絳夋湇鍔″疄鏃剁洃嫻嬫湇鍔″櫒鐘舵? 鎴栬呰嚜宸卞啓紼嬪簭瀹炵幇, 璋冪敤strategy.setAlternateAddresses鍗沖彲.
- removeFailedEndpoint 濡傛灉璁劇疆涓簍rue, 浣嗘病鏈夌洃嫻嬫湇鍔″櫒鐘舵佺殑紼嬪簭, 鏂板鐨勬垨鑰呭媧葷殑鏈嶅姟鍣ㄥ垯鏃犳硶琚仮澶嶅埌鍦板潃鍒楄〃涓?
- 鑰冭檻鍒版晥鐜囧拰鏀寔failover, 璁劇疆鍦板潃鍒楄〃, 縐婚櫎鍦板潃絳夋病鏈夊悓姝ラ攣.
- 鑷姩縐婚櫎澶辮觸鏈嶅姟鍦板潃鏃? 鐩墠浠呮敮鎸佹墜鍔ㄥ湴鍧鍒楄〃, 娌℃湁鑰冭檻wsdl涓殑澶氭湇鍔″湴鍧.
- 鍚庣畫鎴戜細(xì)鍐欎竴涓嬌鐢▃ookeeper澧炲垹鏈嶅姟鍦板潃鍒楄〃鐨勭ず渚? (鏈榪戜篃鍦ㄧ湅zookeeper)
涓昏鐨勪唬鐮侀兘鍦ˋbstractLoadBalanceStrategy 涓? 鍩烘湰鍜?AbstractStaticFailoverStrategy 涓鏍? 娣誨姞浜?jiǎn)涓涓猺emoveAlternateAddress 鐢ㄤ簬縐婚櫎澶辮觸鐨勬湇鍔″湴鍧.
LoadBalanceStrategy 鎺ュ彛鐨勪唬鐮佸涓?
/**
* Supports pluggable strategies for alternate endpoint selection on
* load balance.
* <p/>
* Random, Retries, Mod (later)
* <p/>
* 1. support load balance 2.support fail over.
*
* @author Felix Zhang Date:2010-10-1 18:14
* @see org.apache.cxf.clustering.FailoverStrategy
*/
public interface LoadBalanceStrategy {
/**
* Get the alternate endpoints for this invocation.
*
* @param exchange the current Exchange
* @return a failover endpoint if one is available
*/
List<Endpoint> getAlternateEndpoints(Exchange exchange);
/**
* Select one of the alternate endpoints for a retried invocation.
*
* @param alternates List of alternate endpoints if available
* @return the selected endpoint
*/
Endpoint selectAlternateEndpoint(List<Endpoint> alternates);
/**
* Get the alternate addresses for this invocation.
* These addresses over-ride any addresses specified in the WSDL.
*
* @param exchange the current Exchange
* @return a failover endpoint if one is available
*/
List<String> getAlternateAddresses(Exchange exchange);
/**
* Select one of the alternate addresses for a retried invocation.
*
* @param addresses List of alternate addresses if available
* @return the selected address
*/
String selectAlternateAddress(List<String> addresses);
/**
* should remove failed endpoint or not.
* only work for user defined addresses list.
* @return true or false
*/
boolean isRemoveFailedEndpoint();
/**
* change endpoint every time or not.
* @return boolean
*/
boolean isAlwaysChangeEndpoint();
/**
* remove failed address from list.
* @param address the failed address
*/
void removeAlternateAddress(String address);
}
RandomLoadBalanceStrategy緇ф壙鑷?AbstractLoadBalanceStrategy, 鍜?RandomStrategy鐨勫尯鍒氨鏄幏鍙栦笅涓涓湇鍔″湴鍧鏃跺茍涓嶄粠鍒楄〃涓Щ闄ゆ鍦板潃, 鍚﹀垯灝卞仛涓嶅埌璐熻澆鍧囪 浜?
3. 鏈閲嶈鐨?LoadBalanceTargetSelector
A: 榪欎釜綾繪瘮杈冨鏉? 鎴戜滑涓轟簡(jiǎn)瀹炵幇璐熻澆鍧囪 , 淇敼浜?strong>prepare鏉ュ姩鎬佽緗皟鐢ㄧ殑endpoint, 鏇挎崲絳栫暐鍙栧喅浜嶭oadBalanceStrategy
涓昏浠g爜濡備笅:
boolean existsEndpoint = false;
//check current endpoint is not null
Endpoint theEndpoint = exchange.get(Endpoint.class);
if (theEndpoint.getEndpointInfo().getAddress() != null) {
existsEndpoint = true;
}
Endpoint nextEndpoint;
if (getStrategy().isAlwaysChangeEndpoint() || !existsEndpoint) {
//get a endpoint and set to current endpoint
Endpoint loadBalanceTarget = getLoadBalanceTarget(exchange);
if (loadBalanceTarget != null) {
logger.info("switch to next target: " + loadBalanceTarget.getEndpointInfo().getAddress());
setEndpoint(loadBalanceTarget);
//update exchange.org.apache.cxf.message.Message.ENDPOINT_ADDRESS --- 涓嶈緗繖涓氨鐢ㄤ笂嬈$殑
濂囨?/span>
message.put(Message.ENDPOINT_ADDRESS, loadBalanceTarget.getEndpointInfo().getAddress());
}
nextEndpoint = loadBalanceTarget;
} else {
//use current endpoint
nextEndpoint = theEndpoint;
}
B:涓轟簡(jiǎn)鍜屽師鏈塅ailover鐗規(guī)у吋瀹? 鎴戜滑淇敼浜?getFailoverTarget鍑芥暟, 鍦ㄦ鍑芥暟涓縐婚櫎澶辮觸鐨勬湇鍔″湴鍧, 鍥犱負(fù)鍦ㄤ箣鍓嶆垜浠慨鏀逛簡(jiǎn)LoadBalanceStrategy, 瀹冨湪鑾峰彇鍦板潃鏃朵笉鍐嶇Щ闄ゅ綋鍓嶅湴鍧, 鎵浠ユ垜浠渶瑕佹墜鍔ㄧЩ闄?
閮ㄥ垎浠g爜濡備笅:
String currentAddress = getEndpoint().getEndpointInfo().getAddress();
//failover should remove current endpoint first, then get next -- 鏍規(guī)嵁瀹氫箟鐨勭瓥鐣ユ潵鍐沖畾鏄惁浠庡叏灞鍦板潃鍒楄〃涓Щ闄?/span>
if (getStrategy().isRemoveFailedEndpoint()) {
logger.warn("remove current failed address: " + currentAddress);
//remove for client, not for current invocation -- 娌℃湁鍚屾閿?/span>
getStrategy().removeAlternateAddress(currentAddress);
}
//remove for current invocation: 褰撳墠璇鋒眰涓繪槸縐婚櫎澶辮觸鏈嶅姟鍦板潃
alternateAddresses.remove(currentAddress);
String alternateAddress =
getStrategy().selectAlternateAddress(alternateAddresses);
4. 璋冪敤瀹炰緥:
姝ゅ鎴戜滑閲囩敤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"
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://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">
<util:list id="addressList">
<value>http://localhost:8081/service/Hello</value>
<value>http://localhost:8082/service/Hello</value>
<value>http://localhost:8083/service/Hello</value>
<value>http://localhost:8086/service/Hello</value>
<value>http://localhost:8087/service/Hello</value>
<value>http://localhost:8088/service/Hello</value>
</util:list>
<bean id="SequentialAddresses" class="org.apache.cxf.clustering.SequentialStrategy">
<property name="alternateAddresses">
<ref bean="addressList"/>
</property>
</bean>
<bean id="randomAddresses" class="org.javascud.extensions.cxf.RandomLoadBalanceStrategy">
<property name="alternateAddresses">
<ref bean="addressList"/>
</property>
<property name="removeFailedEndpoint" value="true" />
</bean>
<bean id="loadBalanceFeature" class="org.javascud.extensions.cxf.LoadBalanceFeature">
<property name="strategy" ref="randomAddresses" />
</bean>
<jaxws:client name="helloClient"
serviceClass="org.javascud.extensions.cxf.service.Hello" >
<jaxws:features>
<ref bean="loadBalanceFeature" />
</jaxws:features>
</jaxws:client>
</beans>
8081, 8082, 8083鏄疄闄呭瓨鍦ㄧ殑鏈嶅姟, 鍏朵粬鐨勪笉瀛樺湪.
璋冪敤鐨凧ava浠g爜:
package org.javascud.extensions.cxf.loadbalance;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.javascud.extensions.cxf.LoadBalanceStrategy;
import org.javascud.extensions.cxf.service.Hello;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloLoadBalanceAndFailOverClientByXML
{
public static void main(String[] args)
{
ClassPathXmlApplicationContext context
= new ClassPathXmlApplicationContext(new String[]
{"org/javascud/extensions/cxf/loadbalance/loadbalance_fail.xml"});
Hello client = (Hello) context.getBean("helloClient");
LoadBalanceStrategy strategy = (LoadBalanceStrategy) context.getBean("randomAddresses");
Client myclient = ClientProxy.getClient(client);
String address = myclient.getEndpoint().getEndpointInfo().getAddress();
System.out.println(address);
for(int i=1; i<=20; i++)
{
String result1 = client.sayHello("Felix" +i);
System.out.println("Call " + i +": " + result1);
int left = strategy.getAlternateAddresses(null).size();
System.out.println("================== left " + left + " ===========================");
}
}
}
姝ゅ浠呬粎涓烘ā鎷熸祴璇?
5. 鍏充簬嫻嬭瘯鐢ㄤ緥
娌℃兂濂藉浣曞啓鍗曞厓嫻嬭瘯, test閲岄潰鐩墠閮芥槸闅忔剰嫻嬭瘯鐨勪唬鐮? 鍩烘湰鐓ч【鍒版墍鏈夊姛鑳?
6. 涓嬭澆
浠g爜涓嬭澆: http://cnscud.googlecode.com/files/extensions-cxf_20101015.zip
婧愮爜浣嶇疆: http://cnscud.googlecode.com/svn/trunk/extensions/ 鍏朵腑cxf鐩綍鏄鏂囩珷鐩稿叧鐨勬簮鐮?
7. 鏈変換浣曢棶棰樿鐣欒█.
杞澆璇鋒敞鏄庝綔鑰呭拰鍑哄 http://scud.blogjava.net

]]>