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. 给你的Flex程序添加深链接和分析-其实比你想象的要简单
  2. 【C 语言】const 关键字用法 ( 常量指针 - const 在 * 左边 - 修饰数据类型 - 内存不变 | 指针常量 - const 在 * 右边 - 修饰变量 - 指针不变 )
  3. 机器学习算法一览(附python和R代码)
  4. 中国大学单身 (民间)排行榜!你上榜了没
  5. 【Python3爬虫】为什么你的博客没人看呢?
  6. MyBatis-Plus_Condition作用
  7. html文字竖直书写,css 文字竖直居中的写法和图片垂直居中代码(图文)
  8. html无序列表中的正方形点点,CSS 有序或者无序列表的前面的标记 list-style-type 属性的实现...
  9. 存储过程没有执行完后没有释放锁_【大厂面试07期】说一说你对synchronized锁的理解?...
  10. 信息学奥赛一本通(1165:Hermite多项式)
  11. 大牛讲解Kubernetes实战
  12. Cerebro 插件之电影磁力搜索神器
  13. Android Studio 将github作为远程maven仓库
  14. 清华EMBA课程系列思考之四 -- 组织行为学
  15. Visual Basic .NET中操作MsAgent
  16. iis在xp3上的部署
  17. java 密码复杂度_java密码复杂度校验
  18. linux终端vim配色方案,Vim自定义配色方案图文并茂
  19. python中对文件的操作总结
  20. tar命令打包并压缩指定的文件夹并且排除指定的文件

热门文章

  1. linux硬盘和分区,Linux硬盘和分区
  2. Android开发 实现跑马灯效果滚动字幕
  3. 微信公众平台开发(122) 获取微信会员卡用户姓名和手机号
  4. LaTeX命令速查手册 - 方法总比问题多
  5. Android应用程序icon规范
  6. 复旦大学高等代数考试命题的若干经验
  7. textarea的placeholder无效问题解决
  8. 原创力文档c语言题目,C语言智力题目.docx
  9. 三层开发我的一家之言
  10. 西南科技大学数据库实验二(Oracle 11g)