1. 程式人生 > >解決hessian遠端呼叫連線超時的問題

解決hessian遠端呼叫連線超時的問題

目前幾套系統中主要使用的hessian進行遠端呼叫webservice服務的有hessian的HessianProxyFactory(com.caucho.hessian.client.HessianProxyFactory)和spring的HessianProxyFactoryBean(org.springframework.remoting.caucho.HessianProxyFactoryBean).

1.HessianProxyFactory
檢視HessianProxyFactory原始碼後發現,hessian在建立http請求連線webservice服務並沒有對連線超時進行相關的引數設定,所以當網路出現問題就會造成整個hessian處理的阻塞,進而阻塞整個執行緒後續的處理
以下是HessianProxyFactory對連線處理的原始碼

protected URLConnection openConnection(URL url)
 throws IOException
 {
 URLConnection conn = url.openConnection();

 conn.setDoOutput(true);

 if (_readTimeout > 0) {
 try {
 conn.setReadTimeout((int) _readTimeout);
 } catch (Throwable e) {
 }
 }

 conn.setRequestProperty("Content-Type", "x-application/hessian");

 if (_basicAuth != null)
 conn.setRequestProperty("Authorization", _basicAuth);
 else if (_user != null && _password != null) {
 _basicAuth = "Basic " + base64(_user + ":" + _password);
 conn.setRequestProperty("Authorization", _basicAuth);
 }

 return conn;
 }


所以我們針對此邏輯繼承並重寫該openConnection方法,在建立http連線的時候通過設定連線超時時間來解決因網路問題阻塞程式繼續的問題

public class MyHessianProxyFactory extends HessianProxyFactory {

 private int connectTimeOut = 10000;

 private int readTimeOut = 10000;

 public int getConnectTimeOut() {
 return connectTimeOut;
 }

 public void setConnectTimeOut(int connectTimeOut) {
 this.connectTimeOut = connectTimeOut;
 }

 public int getReadTimeOut() {
 return readTimeOut;
 }

 public void setReadTimeOut(int readTimeOut) {
 this.readTimeOut = readTimeOut;
 }

 protected URLConnection openConnection(URL url) throws IOException {
 URLConnection conn = url.openConnection();
 conn.setDoOutput(true);
 if (this.connectTimeOut > 0) {
 conn.setConnectTimeout(this.connectTimeOut);
 }
 if (this.readTimeOut > 0) {
 conn.setReadTimeout(this.readTimeOut);
 }
 conn.setRequestProperty("Content-Type", "x-application/hessian");
 if (_basicAuth != null)
 conn.setRequestProperty("Authorization", _basicAuth);
 else if (_user != null && _password != null) {
 _basicAuth = "Basic " + base64(_user + ":" + _password);
 conn.setRequestProperty("Authorization", _basicAuth);
 }
 return conn;
 }
}


2.HessianProxyFactoryBean
檢視spring的HessianProxyFactoryBean原始碼發現,它在封裝hessian是直接建立一個HessianProxyFactory例項,然後利用該例項完成建立遠端服務

public class HessianProxyFactoryBean extends HessianClientInterceptor implements FactoryBean {

 private Object serviceProxy;


 public void afterPropertiesSet() {
 super.afterPropertiesSet();
 this.serviceProxy = ProxyFactory.getProxy(getServiceInterface(), this);
 }
 

public Object getObject() {
 return this.serviceProxy;
 }

 public Class getObjectType() {
 return getServiceInterface();
 }
 
public boolean isSingleton() {
 return true;
 }

}


所以對此的解決方法與上面差不多,繼承HessianProxyFactoryBean然後加入相應的連線超時和讀取超時的變數,重寫afterPropertiesSet方法,並且同時完成上面第一步對HessianProxyFactory的改造,這樣就能保證連線遠端webserver伺服器時不會因為網路原因阻塞程式的執行

public class MyHessianProxyFactoryBean extends HessianProxyFactoryBean {

 private MyHessianProxyFactory proxyFactory = new MyHessianProxyFactory();

 private int readTimeOut = 10000;

 private int connectTimeOut = 10000;

 public int getReadTimeOut() {
 return readTimeOut;
 }

 public void setReadTimeOut(int readTimeOut) {
 this.readTimeOut = readTimeOut;
 }

 public int getConnectTimeOut() {
 return connectTimeOut;
 }

 public void setConnectTimeOut(int connectTimeOut) {
 this.connectTimeOut = connectTimeOut;
 }

 public void afterPropertiesSet() {
 proxyFactory.setReadTimeout(readTimeOut);
 proxyFactory.setConnectTimeOut(connectTimeOut);
 setProxyFactory(proxyFactory);
 super.afterPropertiesSet();
 }
}