HttpClient通过RetryHandler实现超时重试
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实现超时重试相关推荐
- HttpClient 连接超时重试处理
记录一次HttpClient 连接超时重试问题 原代码如下: public static void main(String[] args) throws UnsupportedEncodingExce ...
- Volley超时重试机制详解
Volley超时重试机制 基础用法 Volley为开发者提供了可配置的超时重试机制,我们在使用时只需要为我们的Request设置自定义的RetryPolicy即可. 参考设置代码如下: int DEF ...
- 谷歌浏览器连接超时_系统超时重试机制(OpenResty/Nginx)
在实际开发当中,很多故障的产生都是因为没有意识到超时设置的重要性而造成的.如果不设置超时机制,就有可能导致连锁反应,最终系统雪崩.有些中间件天然集成了超时重试的机制,但是在设计当中需要注意的是:读服务 ...
- dubbo超时重试和异常处理
dubbo超时重试和异常处理 参考: https://www.cnblogs.com/ASPNET2008/p/7292472.html https://www.tuicool.com/article ...
- 分布式面试 - 如何基于 dubbo 进行服务治理、服务降级、失败重试以及超时重试?
分布式面试 - 如何基于 dubbo 进行服务治理.服务降级.失败重试以及超时重试? 面试题 如何基于 dubbo 进行服务治理.服务降级.失败重试以及超时重试? 面试官心理分析 服务治理,这个问题如 ...
- Dubbo(十一)dubbo的超时重试配置以及启动检查
一.dubbo超时重试配置 dubbo重试次数配置使用的是retries 属性.可以配置于服务提供者.消费者的接口方法.接口类.以及全局配置范围上.与超时配置优先级一样遵循就近原则,方法上的配置优先于 ...
- 面试系列26 如何基于dubbo进行服务治理、服务降级、失败重试以及超时重试
(1)服务治理 1)调用链路自动生成 一个大型的分布式系统,或者说是用现在流行的微服务架构来说吧,分布式系统由大量的服务组成.那么这些服务之间互相是如何调用的?调用链路是啥?说实话,几乎到后面没人搞的 ...
- 怎样实现一个非阻塞的超时重试任务队列
起因 最近接手一个项目,要把其中的阻塞任务队列,重构成非阻塞.在客户端很少有机会直接处理任务队列.项目完成需要总结经验 阻塞的发生 我这里先说明我遇到的阻塞问题,我这里的阻塞不是多线程访问的阻塞,概念 ...
- httpclient的post请求超时
前两天做项目,使用httpclient的post请求超时,检查代码也没问题.后来偶然在看日志的时候才发现问题所在. 现象 当post请求的返回数据少的时候应用没问题.当post请求返回的数据量在deb ...
最新文章
- 给你的Flex程序添加深链接和分析-其实比你想象的要简单
- 【C 语言】const 关键字用法 ( 常量指针 - const 在 * 左边 - 修饰数据类型 - 内存不变 | 指针常量 - const 在 * 右边 - 修饰变量 - 指针不变 )
- 机器学习算法一览(附python和R代码)
- 中国大学单身 (民间)排行榜!你上榜了没
- 【Python3爬虫】为什么你的博客没人看呢?
- MyBatis-Plus_Condition作用
- html文字竖直书写,css 文字竖直居中的写法和图片垂直居中代码(图文)
- html无序列表中的正方形点点,CSS 有序或者无序列表的前面的标记 list-style-type 属性的实现...
- 存储过程没有执行完后没有释放锁_【大厂面试07期】说一说你对synchronized锁的理解?...
- 信息学奥赛一本通(1165:Hermite多项式)
- 大牛讲解Kubernetes实战
- Cerebro 插件之电影磁力搜索神器
- Android Studio 将github作为远程maven仓库
- 清华EMBA课程系列思考之四 -- 组织行为学
- Visual Basic .NET中操作MsAgent
- iis在xp3上的部署
- java 密码复杂度_java密码复杂度校验
- linux终端vim配色方案,Vim自定义配色方案图文并茂
- python中对文件的操作总结
- tar命令打包并压缩指定的文件夹并且排除指定的文件