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