目前的項目接口都是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); } }