Spring web之restTemplate超时问题处理
问题
项目中有个远程服务因为某些原因会访问不通,于是就在调用的那一步挂起无法结束了。
查看代码
代码大概如下
CloseableHttpClient closeableHttpClient = HttpClients.custom() .setConnectionManager(manager) .build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();requestFactory.setHttpClient(httpClient);clientHttpRequestFactory.setConnectTimeout(1000);RestTemplate restTemplate = new RestTemplate();restTemplate.setRequestFactory(requestFactory);
分析
HttpComponentsClientHttpRequestFactory底层默认使用了apache的HttpClient,超时设置就针对其设置的。其实我们只需要设置ReadTimeout就好了。
CloseableHttpClient closeableHttpClient = HttpClients.custom()
.setConnectionManager(manager)
.build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
clientHttpRequestFactory.setConnectTimeout(1000);
clientHttpRequestFactory.setReadTimeout(50);
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(requestFactory);
但我们发现,我们并没有使用默认的HttpClient,而是显式的指定了Client,我们在创建Client的时候也可以指定其的各种超时属性:
RequestConfig defaultRequestConfig = RequestConfig.custom()
.setConnectTimeout(2 * 1000)
.setSocketTimeout(5 * 1000)
.setConnectionRequestTimeout(2 * 1000)
.build(); CloseableHttpClient closeableHttpClient = HttpClients.custom()
.setDefaultRequestConfig(getRequestConfig())
.setConnectionManager(manager)
.build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
clientHttpRequestFactory.setConnectTimeout(1000);
clientHttpRequestFactory.setReadTimeout(50);
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(requestFactory);
上面可以看到,我们在创建Client的时候指定了超时时间,也在创建HttpComponentsClientHttpRequestFactory的时候指定了超时时间,那么到底以哪个为准呢?
一探究竟
项目中使用的是spring web 4.3.5, 我们看看源代码的实现,以下是HttpComponentsClientHttpRequestFactory类的部分方法:
/**
* Set the socket read timeout for the underlying HttpClient.
* A timeout value of 0 specifies an infinite timeout.
* <p>Additional properties can be configured by specifying a
* {@link RequestConfig} instance on a custom {@link HttpClient}.
* @param timeout the timeout value in milliseconds
* @see RequestConfig#getSocketTimeout()
*/
public void setReadTimeout(int timeout) {
Assert.isTrue(timeout >= 0, "Timeout must be a non-negative value");
this.requestConfig = requestConfigBuilder().setSocketTimeout(timeout).build();
setLegacySocketTimeout(getHttpClient(), timeout);
}
@Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri);
postProcessHttpRequest(httpRequest);
HttpContext context = createHttpContext(httpMethod, uri);
if (context == null) {
context = HttpClientContext.create();
} // Request configuration not set in the context
if (context.getAttribute(HttpClientContext.REQUEST_CONFIG) == null) {
// Use request configuration given by the user, when available
RequestConfig config = null;
if (httpRequest instanceof Configurable) {
config = ((Configurable) httpRequest).getConfig();
}
if (config == null) {
config = createRequestConfig(getHttpClient());
}
if (config != null) {
context.setAttribute(HttpClientContext.REQUEST_CONFIG, config);
}
} if (this.bufferRequestBody) {
return new HttpComponentsClientHttpRequest(getHttpClient(), httpRequest, context);
}
else {
return new HttpComponentsStreamingClientHttpRequest(getHttpClient(), httpRequest, context);
}
}
/**
* Create a default {@link RequestConfig} to use with the given client.
* Can return {@code null} to indicate that no custom request config should
* be set and the defaults of the {@link HttpClient} should be used.
* <p>The default implementation tries to merge the defaults of the client
* with the local customizations of this factory instance, if any.
* @param client the {@link HttpClient} (or {@code HttpAsyncClient}) to check
* @return the actual RequestConfig to use (may be {@code null})
* @since 4.2
* @see #mergeRequestConfig(RequestConfig)
*/
protected RequestConfig createRequestConfig(Object client) {
if (client instanceof Configurable) {
RequestConfig clientRequestConfig = ((Configurable) client).getConfig();
return mergeRequestConfig(clientRequestConfig);
}
return this.requestConfig;
}
/**
* Merge the given {@link HttpClient}-level {@link RequestConfig} with
* the factory-level {@link RequestConfig}, if necessary.
* @param clientConfig the config held by the current
* @return the merged request config
* @since 4.2
*/
protected RequestConfig mergeRequestConfig(RequestConfig clientConfig) {
if (this.requestConfig == null) { // nothing to merge
return clientConfig;
} RequestConfig.Builder builder = RequestConfig.copy(clientConfig);
int connectTimeout = this.requestConfig.getConnectTimeout();
if (connectTimeout >= 0) {
builder.setConnectTimeout(connectTimeout);
}
int connectionRequestTimeout = this.requestConfig.getConnectionRequestTimeout();
if (connectionRequestTimeout >= 0) {
builder.setConnectionRequestTimeout(connectionRequestTimeout);
}
int socketTimeout = this.requestConfig.getSocketTimeout();
if (socketTimeout >= 0) {
builder.setSocketTimeout(socketTimeout);
}
return builder.build();
}
我们可以看到,版本4.2之后,如果二者都进行了参数指定,会有一个mergeRequestConfig的操作,超时以HttpComponentsClientHttpRequestFactory类指定为为准。
结论
所以,针对本文一开始的问题,我们只需要设置HttpComponentsClientHttpRequestFactory实例的setReadTimeout方法即可。
参考
https://leokongwq.github.io/2018/11/21/springboot-resttempate-timout.html
https://www.cnblogs.com/softidea/p/6964347.html
但我们发现,我们显式的指定了Client,我们在创建Client的时候可以指定其的各种超时属性:
Spring web之restTemplate超时问题处理的更多相关文章
- Spring Cloud ZooKeeper集成Feign的坑1,错误:Consider defining a bean of type 'org.springframework.web.client.RestTemplate' in your configuration.
错误如下: ERROR 31473 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** A ...
- spring web.xml 难点配置总结
web.xml web.xml是所有web项目的根源,没有它,任何web项目都启动不了,所以有必要了解相关的配置. ContextLoderListener,ContextLoaderServlet, ...
- Spring Boot使用RestTemplate消费REST服务的几个问题记录
我们可以通过Spring Boot快速开发REST接口,同时也可能需要在实现接口的过程中,通过Spring Boot调用内外部REST接口完成业务逻辑. 在Spring Boot中,调用REST Ap ...
- spring web.xml 难点配置总结【转】
web.xml web.xml是所有web项目的根源,没有它,任何web项目都启动不了,所以有必要了解相关的配置. ContextLoderListener,ContextLoaderServlet, ...
- 001-快速搭建Spring web应用【springboot 2.0.4】-gradle、springboot的启动过程分析、gradle多模块构建
一.概述 学习<精通Spring MVC4>书籍笔记 二.笔记 1.快速构建Spring starter web项目几种方式 1>使用Spring Tool Suite生成Start ...
- spring boot 注入 restTemplate
转载自:http://blog.csdn.net/liuchuanhong1/article/details/54631080 package com.chhliu.springboot.restfu ...
- Spring WebClient vs. RestTemplate
1. 简介 本教程中,我们将对比 Spring 的两种 Web 客户端实现 -- RestTemplate 和 Spring 5 中全新的 Reactive 替代方案 WebClient. 2. 阻塞 ...
- 使用 Spring 提供的 restTemplate 完成 Http 服务消费
RestTemplate 介绍 RestTemplate 是 Spring 提供的用于访问 Rest 服务的客户端,RestTemplate 提供了多种便捷访问远程 Http 服务的方法,能够大大提高 ...
- Consider defining a bean of type 'org.springframework.web.client.RestTemplate' in your configuration
https://www.cnblogs.com/EasonJim/p/7546136.html 错误如下: ERROR 31473 --- [ main] o.s.b.d.LoggingFailure ...
随机推荐
- Nginx 路由转发和反向代理 location 配置
Nginx 配置的三种方式 第一种直接替换 location 匹配部分 第二种 proxy_pass 的目标地址,默认不带 /,表示只代理域名,url 和参数部分不会变(把请求的 path 拼接到 p ...
- leetcode 730. 统计不同回文子序列(区间dp,字符串)
题目链接 https://leetcode-cn.com/problems/count-different-palindromic-subsequences/ 题意 给定一个字符串,判断这个字符串中所 ...
- Centos7 虚拟机优化
配置yum源 rm -f /etc/yum.repos.d/* curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/ ...
- 关于Vue v-model你需要知道的一切
v-model是Vue的一个指令,它提供了input和form数据之间或两个组件之间的双向数据绑定. 这在Vue开发中是一个简单的概念,但是v-model的真正威力需要一些时间才能理解. 到本教程结 ...
- 基于循环队列的BFS的原理及实现
文章首发于微信公众号:几何思维 1.故事起源 有一只蚂蚁出去寻找食物,无意中进入了一个迷宫.蚂蚁只能向上.下.左.右4个方向走,迷宫中有墙和水的地方都无法通行.这时蚂蚁犯难了,怎样才能找出到食物的最短 ...
- centos7防火墙firewalld拒绝某ip或者某ip段访问服务器任何服务
安装firewall后(LINUX7系统一般情况下默认已安装),防火墙默认配置是只打开SSH端口的,也就是22端口,如果SSH的端口已更改成别的端口了,请切记一定在启动firewall前先修改对应服务 ...
- (12)-Python3之--openpyxl模块
1.安装 pip install openpyxl 2.Excel操作的流程 1.打开excel,进入工作薄 workbook2.选择表单 Sheet 3.单元格 Cell4.读写操作 3.Exce ...
- CentOS 镜像下载地址
CentOS镜像地址:http://isoredirect.centos.org/altarch/7/isos/i386/
- Jenkins部署web项目到Tomcat(热部署)
使用这个方式的话需要tomcat中有初始时Manage这个项目,本质上是通过http://ip:port/manager/html这个地址的上传接口进行上传,进行热部署(需要远程tomcat 必须开启 ...
- JasperReports 取消自动分页/忽略分页
因为需要将合同比价单由PDF文档形式改为HTML页面方式,虽然转换文档类型了,但是发现HTML页面中间到了一定行数就出现了空行把Detail给隔开了.之前总想着怎样消除中间空行,以为是报表top页面边 ...