HttpMethod自定义失败重连

我们做web开发时,需要经常使用httpclient来请求http服务,有时为了安全起见,服务提供方会提供多个http地址,这样如果我们请求某个ip出现异常,可以重试其他的ip地址,来尽量保证系统的稳定,以下是自定义一个HttpMethod重试机制的简要代码。

HostCluster类定义需要连接的协议、ips[]、重试次数、随机获取一个host等:

点击(此处)折叠或打开

  1. public class HostCluster {
  2.     protected static final String HTTP_PROTOCOL = \"http\";
  3.     protected static final String HTTPS_PROTOCOL = \"https\";

  4.     protected String protocol;
  5.     protected String[] ips; //contain ip and port

  6.     private int idx;
  7.     private int retry;

  8.     private Random random;

  9.     public HostCluster(String ipAndPort) {
  10.         this(HTTP_PROTOCOL, ipAndPort);
  11.     }

  12.     public HostCluster(String protocol, String ipAndPort) {
  13.         this(protocol, ipAndPort, 0);
  14.     }

  15.     public HostCluster(String protocol, String ipAndPort, int retry) {
  16.         if (StringUtils.isEmpty(ipAndPort)) {
  17.             throw new IllegalArgumentException(\"invalid constructor params.\");
  18.         }
  19.         if (retry < 0) {
  20.             throw new IllegalArgumentException(\"invalid retry.\");
  21.         }
  22.         if (!HTTP_PROTOCOL.equals(protocol) && !HTTPS_PROTOCOL.equals(protocol)) {
  23.             throw new IllegalArgumentException(\"invalid protocol.\");
  24.         }
  25.         
  26.         //split the string
  27.         String[] splitStr = StringUtils.split(ipAndPort, \",\");

  28.         this.protocol = protocol;
  29.         this.ips = splitStr;
  30.         this.retry = retry;

  31.         this.idx = this.ips.length;
  32.         this.random = new Random();
  33.     }

  34.     public String randomHost() {
  35.         int index = this.random.nextInt(idx);
  36.         log.info(\"randomIp=\" + ips[index]);
  37.         return this.protocol + \"://\" + ips[index];
  38.     }

  39.     public boolean isHttps() {
  40.         return HTTPS_PROTOCOL.equals(protocol);
  41.     }

  42.     public String getProtocol() {
  43.         return protocol;
  44.     }

  45.     public int getRetry() {
  46.         return retry;
  47.     }
  48. }


ClusterRetryHttpMethod从HostCluster获取的randomHost,然后new URI()设置相应的base(GetMethod or PostMethod)

点击(此处)折叠或打开

  1. public abstract class ClusterRetryHttpMethod<T extends HttpMethod> {
  2.     protected HostCluster cluster;
  3.     protected String urlSuffix;
  4.     protected T base;
  5.     private Integer retry;

  6.     public ClusterRetryHttpMethod(HostCluster cluster, String urlSuffix) {
  7.         this(cluster, urlSuffix, null);
  8.     }

  9.     public ClusterRetryHttpMethod(HostCluster cluster, String urlSuffix, Integer retry) {
  10.         if (cluster == null || StringUtils.isBlank(urlSuffix)) {
  11.             throw new IllegalArgumentException(\"invalid params.\");
  12.         }
  13.         if (retry != null) {
  14.             if (retry < 0) {
  15.                 throw new IllegalArgumentException(\"invalid retry.\");
  16.             } else {
  17.                 this.retry = retry;
  18.             }
  19.         }
  20.         this.cluster = cluster;
  21.         this.urlSuffix = urlSuffix;

  22.         this.base = initBase();
  23.     }

  24.     public boolean isHttps() {
  25.         return this.cluster.isHttps();
  26.     }

  27.     public void setQueryString(String queryString) {
  28.         this.base.setQueryString(queryString);
  29.     }

  30.     public void setQueryString(NameValuePair[] params) {
  31.         this.base.setQueryString(params);
  32.     }

  33.     public int getRetry() {
  34.         return retry == null ? this.cluster.getRetry() : retry;
  35.     }

  36.     protected abstract T initBase();//子类各自实现,GetMethod or PostMethod

  37.     public T randomMethod() throws Exception {
  38.         String url = this.randomUrl();
  39.         if (StringUtils.isBlank(url)) {
  40.             url = \"/\";
  41.         }

  42.         this.base.setURI(new URI(url, true));
  43.         return base;
  44.     }

  45.     protected String randomUrl() {
  46.         return cluster.randomHost() + urlSuffix;
  47.     }
  48. }


最后就是怎么调用了,这里使用的是HttpClientPool来调用http连接,关于HttpClientPool详见我的另一篇文章:http://blog.itpub.net/28912557/viewspace-1223241/

点击(此处)折叠或打开

  1. public class HttpClientPool extends GenericObjectPool<HttpClient> {

  2.     private int httpsPort;

  3.     public HttpClientPool(PoolableObjectFactory<HttpClient> factory) {
  4.         super(factory);
  5.     }

  6.     public <T> T doPost(ClusterRetryHttpMethod method, HttpClientDataCallback<T> callback) {
  7.         HttpClient toUse = null;
  8.         HttpMethod m = null;
  9.         int index = 0;
  10.         if (method == null) {
  11.             return null;
  12.         }
  13.         if (method.isHttps()) {
  14.             Protocol myhttps = new Protocol(\"https\", new SSLProtocolSocketFactoryImpl(), httpsPort);
  15.             Protocol.registerProtocol(\"https\", myhttps);
  16.         }
  17.         try {
  18.             toUse = borrowObject();
  19.             while (index <= method.getRetry()) {
  20.                 try {
  21.                     m = method.randomMethod();
  22.                     toUse.executeMethod(m);
  23.                     T rel = callback.handleResponse(m.getResponseBodyAsString());
  24.                     return rel;
  25.                 } catch (Exception e) {
  26.                     logger.error(\"failed to execute http request.\", e);
  27.                     index++;
  28.                 } finally {
  29.                     try {
  30.                         m.releaseConnection();
  31.                     } catch (Exception e) {
  32.                         // in case fail, ignore and return object
  33.                     }
  34.                 }
  35.             }
  36.         } catch (Exception e) {
  37.             return null;
  38.         } finally {
  39.             if (toUse != null) {
  40.                 try {
  41.                     returnObject(toUse);
  42.                 } catch (Exception e) {
  43.                 }
  44.             }
  45.             if (method.isHttps()) {
  46.                 try {
  47.                     Protocol.unregisterProtocol(\"https\");
  48.                 } catch (Exception e) {
  49.                 }
  50.             }
  51.         }
  52.         // all retry failed
  53.         return null;

  54.     }


  55.     public int getHttpsPort() {
  56.         return httpsPort;
  57.     }

  58.     public void setHttpsPort(int httpsPort) {
  59.         this.httpsPort = httpsPort;
  60.     }
  61. }


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/28912557/viewspace-1356116/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/28912557/viewspace-1356116/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值