java项目中使用apache httpclient进行数据传输、访问,目前程序中涉及到需要callback操作,product需要被动的接收consume的处理状态,为了最大程度的能够callback成功因此consume在http调用出现问题(如:服务不可用、异常、超时)情况下需要进行重试(retry request),在这里我列举出我找到的retry方案,有些成功有些不成功。

我是用的httpclient版本是4.5.2。关于retry功能我在网上也找了不少的资料,但是都不是我对应的httpclient版本,大多是过时的。

在httpclient版本4.5.2提供了以下几种retry方案:

StandardHttpRequestRetryHandler

这种方案没有测试通过,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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

如下测试代码:

@Testpublic 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);}}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

运行测试,当url错误、后台报错、后台超时等情况的时候不能进行retry,因此放弃了此方案。

DefaultHttpRequestRetryHandler

这种方案没有测试通过,和上面的StandardHttpRequestRetryHandler类似,它提供了一种默认的retry方案,并没有像StandardHttpRequestRetryHandler一样约定接口必须是冥等的,如下,是我定义的httpclient pool,

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;}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

如下是测试代码:

@Testpublic 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);}}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

依然没有达到希望的效果。

HttpRequestRetryHandler

可以实现,但是不够完美。在官方文档有这么一段,如下,

HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {public boolean retryRequest(IOException exception,int executionCount,HttpContext context) {if (executionCount >= 5) {// Do not retry if over max retry countreturn false;}if (exception instanceof InterruptedIOException) {// Timeoutreturn false;}if (exception instanceof UnknownHostException) {// Unknown hostreturn false;}if (exception instanceof ConnectTimeoutException) {// Connection refusedreturn false;}if (exception instanceof SSLException) {// SSL handshake exceptionreturn false;}HttpClientContext clientContext = HttpClientContext.adapt(context);HttpRequest request = clientContext.getRequest();boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);if (idempotent) {// Retry if the request is considered idempotentreturn true;}return false;}};
CloseableHttpClient httpclient = HttpClients.custom().setRetryHandler(myRetryHandler).build();

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

自定义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 countreturn false;}if (exception instanceof InterruptedIOException) {// Timeoutreturn false;}if (exception instanceof UnknownHostException) {// Unknown hostreturn false;}if (exception instanceof ConnectTimeoutException) {// Connection refusedreturn false;}if (exception instanceof SSLException) {// SSL handshake exceptionreturn false;}HttpClientContext clientContext = HttpClientContext.adapt(context);HttpRequest request = clientContext.getRequest();boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);if (idempotent) {// Retry if the request is considered idempotentreturn 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;}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

如下测试代码:

@Testpublic 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);}}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这种方案,可以实现retry,并且可以根据我的需求进行retry,如:retry count,但是就不能控制retry时间的间隔,也只好放弃了,继续寻找找到了下面这个ServiceUnavailableRetryStrategy

ServiceUnavailableRetryStrategy

可以实现,满足需求,这具有HttpRequestRetryHandler的所有优点,并且可以自定义retry时间的间隔,如下,是我定义的httpclient pool,

public static CloseableHttpClient getHttpClient() {ServiceUnavailableRetryStrategy serviceUnavailableRetryStrategy = new ServiceUnavailableRetryStrategy() {/*** retry逻辑*/@Overridepublic boolean retryRequest(HttpResponse response, int executionCount, HttpContext context) {if (executionCount <= 3)return true;elsereturn false;}/*** retry间隔时间*/@Overridepublic 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;}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

如下是测试代码:

@Testpublic 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);}}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

HttpClient通过RetryHandler实现超时重试相关推荐

  1. HttpClient 连接超时重试处理

    记录一次HttpClient 连接超时重试问题 原代码如下: public static void main(String[] args) throws UnsupportedEncodingExce ...

  2. Volley超时重试机制详解

    Volley超时重试机制 基础用法 Volley为开发者提供了可配置的超时重试机制,我们在使用时只需要为我们的Request设置自定义的RetryPolicy即可. 参考设置代码如下: int DEF ...

  3. 谷歌浏览器连接超时_系统超时重试机制(OpenResty/Nginx)

    在实际开发当中,很多故障的产生都是因为没有意识到超时设置的重要性而造成的.如果不设置超时机制,就有可能导致连锁反应,最终系统雪崩.有些中间件天然集成了超时重试的机制,但是在设计当中需要注意的是:读服务 ...

  4. dubbo超时重试和异常处理

    dubbo超时重试和异常处理 参考: https://www.cnblogs.com/ASPNET2008/p/7292472.html https://www.tuicool.com/article ...

  5. 分布式面试 - 如何基于 dubbo 进行服务治理、服务降级、失败重试以及超时重试?

    分布式面试 - 如何基于 dubbo 进行服务治理.服务降级.失败重试以及超时重试? 面试题 如何基于 dubbo 进行服务治理.服务降级.失败重试以及超时重试? 面试官心理分析 服务治理,这个问题如 ...

  6. Dubbo(十一)dubbo的超时重试配置以及启动检查

    一.dubbo超时重试配置 dubbo重试次数配置使用的是retries 属性.可以配置于服务提供者.消费者的接口方法.接口类.以及全局配置范围上.与超时配置优先级一样遵循就近原则,方法上的配置优先于 ...

  7. 面试系列26 如何基于dubbo进行服务治理、服务降级、失败重试以及超时重试

    (1)服务治理 1)调用链路自动生成 一个大型的分布式系统,或者说是用现在流行的微服务架构来说吧,分布式系统由大量的服务组成.那么这些服务之间互相是如何调用的?调用链路是啥?说实话,几乎到后面没人搞的 ...

  8. 怎样实现一个非阻塞的超时重试任务队列

    起因 最近接手一个项目,要把其中的阻塞任务队列,重构成非阻塞.在客户端很少有机会直接处理任务队列.项目完成需要总结经验 阻塞的发生 我这里先说明我遇到的阻塞问题,我这里的阻塞不是多线程访问的阻塞,概念 ...

  9. httpclient的post请求超时

    前两天做项目,使用httpclient的post请求超时,检查代码也没问题.后来偶然在看日志的时候才发现问题所在. 现象 当post请求的返回数据少的时候应用没问题.当post请求返回的数据量在deb ...

最新文章

  1. 软件工程个人作业01
  2. Python 自动给人脸 戴口罩
  3. Redis:事务、管道、Lua脚本
  4. 请问在JAVA编程中什么叫耦合?什么又叫解藕? 悬赏分:0 - 解决时间:2008-3-8 12:55...
  5. HDU多校联合赛(1007 Magical Forest)模拟题
  6. 升级AndroidStudio3.4问题汇总
  7. Python基础-高级变量类型
  8. WIN2003 IIS6.0+PHP+ASP+MYSQL优化配置
  9. 物料编码在PDM与ERP集成中的应用研究
  10. ibm刀片服务器 维护,IBM刀片服务器 一刀搞定企业信息化
  11. hibernate官网下载
  12. Python ADF 单位根检验 如何查看结果
  13. 苍蓝誓约服务器维护什么时候结束,《苍蓝誓约》12月10日09:30停服维护公告
  14. Android WebView 选择图片并上传(调用相机拍照/相册/选择文件)
  15. 制作html语言网站全攻略,(网页制作HTML代码全攻略.doc
  16. 招生啦!清华大学SIGS人工智能硕士项目2021年硕士研究生普通招考说明
  17. range在python中什么意思_python中range什么意思?
  18. 打开共享文件提示服务器空间不足,访问网络共享报告“服务器存储空间不足,无法处理此命令”...
  19. CSU1041——单词统计
  20. android文字转语音模板,Android-文字转语音

热门文章

  1. Eclipse Git配置
  2. 科学,宗教和信仰,以及神
  3. ArrayMap 源码的详细解析
  4. 复合字面量(compound literals)详解
  5. Qt实用技巧:QtCreator编辑区关闭右侧不必要的警告提示
  6. 个人信用卡融资你了解过吗?
  7. 电动车控制器c语言编程,电动车控制器功能要求 - 最经典电动自行车控制器设计方案...
  8. RabbitMQ-客户端源码之AMQChannel
  9. 微信小程序定义公共方法
  10. 继承——Person为父类,Teacher和Student都继承Person