目前的项目接口都是http,所以在Java项目中使用apache httpclient进行数据传输、访问。html
目前程序中涉及到须要callback操做,product须要被动的接收consume的处理状态,为了最大程度的可以callback成功所以consume在http调用出现问题(如:服务不可用、异常、超时)状况下须要进行重试(retry request),在这里我列举出我找到的retry方案,有些成功有些不成功。java 我是用的httpclient版本是 在httpclient版本 |
这种方案没有测试经过,StandardHttpRequestRetryHandler
其实是DefaultHttpRequestRetryHandler
的子类,这是官方提供的一个标准的retry方案,为了保证幂等性约定resetful接口必须是GET, HEAD, PUT, DELETE, OPTIONS, and TRACE
中的一种,以下,是我定义的httpclient pool测试
public static CloseableHttpClient getHttpClient() { PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); cm.setMaxTotal(MAX_TOTAL); cm.setDefaultMaxPerRoute(MAX_PERROUTE); CloseableHttpClient httpClient = HttpClients .custom() .setRetryHandler(new StandardHttpRequestRetryHandler()) .setConnectionManager(cm) .build(); return httpClient; }
以下是个人测试代码ui
@Test public void test6(){ HttpPost httpPost=new HttpPost("http://127.0.0.1:8080/testjobs1"); try { rsp=httpClient.execute(httpPost); log.info(">> {}",rsp.getStatusLine().getStatusCode()); } catch (Exception e) { log.error(e.getMessage(),e); }finally{ HttpUtil.close(rsp); } }
运行测试,当url错误、后台报错、后台超时等状况的时候不能进行retry,所以放弃了此方案。url
这种方案没有测试经过,和上面的StandardHttpRequestRetryHandler
相似,它提供了一种默认的retry方案,并无像StandardHttpRequestRetryHandler
同样约定接口必须是冥等的,以下,是我定义的httpclient poolspa
public static CloseableHttpClient getHttpClient() { PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); cm.setMaxTotal(MAX_TOTAL); cm.setDefaultMaxPerRoute(MAX_PERROUTE); CloseableHttpClient httpClient = HttpClients .custom() .setRetryHandler(new DefaultHttpRequestRetryHandler()) .setConnectionManager(cm) .build(); return httpClient; }
以下是个人测试代码.net
@Test public void test6(){ HttpPost httpPost=new HttpPost("http://127.0.0.1:8080/testjobs1"); try { rsp=httpClient.execute(httpPost); log.info(">> {}",rsp.getStatusLine().getStatusCode()); } catch (Exception e) { log.error(e.getMessage(),e); }finally{ HttpUtil.close(rsp); } }
依然没有达到但愿的效果。code
能够实现,可是不够完美。在官方文档有这么一段,以下,
HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() { public boolean retryRequest( IOException exception, int executionCount, HttpContext context) { if (executionCount >= 5) { // Do not retry if over max retry count return false; } if (exception instanceof InterruptedIOException) { // Timeout return false; } if (exception instanceof UnknownHostException) { // Unknown host return false; } if (exception instanceof ConnectTimeoutException) { // Connection refused return false; } if (exception instanceof SSLException) { // SSL handshake exception return false; } HttpClientContext clientContext = HttpClientContext.adapt(context); HttpRequest request = clientContext.getRequest(); boolean idempotent = !(request instanceof HttpEntityEnclosingRequest); if (idempotent) { // Retry if the request is considered idempotent return true; } return false; } }; CloseableHttpClient httpclient = HttpClients.custom().setRetryHandler(myRetryHandler).build();
自定义retry实现,这比较灵活,能够根据异常自定义retry机制以及重试次数,而且能够拿到返回信息,以下,是我定义的httpclient pool
public static CloseableHttpClient getHttpClient() { HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler() { public boolean retryRequest( IOException exception, int executionCount, HttpContext context) { if (executionCount >= 5) { // Do not retry if over max retry count return false; } if (exception instanceof InterruptedIOException) { // Timeout return false; } if (exception instanceof UnknownHostException) { // Unknown host return false; } if (exception instanceof ConnectTimeoutException) { // Connection refused return false; } if (exception instanceof SSLException) { // SSL handshake exception return false; } HttpClientContext clientContext = HttpClientContext.adapt(context); HttpRequest request = clientContext.getRequest(); boolean idempotent = !(request instanceof HttpEntityEnclosingRequest); if (idempotent) { // Retry if the request is considered idempotent return true; } return false; } }; PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); cm.setMaxTotal(MAX_TOTAL); cm.setDefaultMaxPerRoute(MAX_PERROUTE); CloseableHttpClient httpClient = HttpClients .custom() .setRetryHandler(retryHandler) .setConnectionManager(cm) .build(); return httpClient; }
以下是个人测试代码
@Test public void test6(){ HttpPost httpPost=new HttpPost("http://127.0.0.1:8080/testjobs1"); try { rsp=httpClient.execute(httpPost); log.info(">> {}",rsp.getStatusLine().getStatusCode()); } catch (Exception e) { log.error(e.getMessage(),e); }finally{ HttpUtil.close(rsp); } }
这种方案,能够实现retry,而且能够根据个人需求进行retry,如:retry count,可是就不能控制retry时间的间隔,也只好放弃了,继续寻找找到了下面这个ServiceUnavailableRetryStrategy
。
能够实现,知足需求,这具备HttpRequestRetryHandler
的全部有点,而且能够自定义retry时间的间隔,以下,是我定义的httpclient pool,
public static CloseableHttpClient getHttpClient() { ServiceUnavailableRetryStrategy serviceUnavailableRetryStrategy = new ServiceUnavailableRetryStrategy() { /** * retry逻辑 */ @Override public boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) { if (executionCount <= 3) return true; else return false; } /** * retry间隔时间 */ @Override public long getRetryInterval() { return 2000; } }; PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); cm.setMaxTotal(MAX_TOTAL); cm.setDefaultMaxPerRoute(MAX_PERROUTE); CloseableHttpClient httpClient = HttpClients.custom().setRetryHandler(new DefaultHttpRequestRetryHandler()) .setConnectionManager(cm).build(); return httpClient; }
以下是个人测试代码
@Test public void test6(){ HttpPost httpPost=new HttpPost("http://127.0.0.1:8080/testjobs1"); try { rsp=httpClient.execute(httpPost); log.info(">> {}",rsp.getStatusLine().getStatusCode()); } catch (Exception e) { log.error(e.getMessage(),e); }finally{ HttpUtil.close(rsp); } }