首先超时不只一种,是接口超时,还是restTemplate超时。
接口超时: 别人访问该项目
restTemplate(或httpClient)超时: 该项目请求其他地址
restTemplate超时设置
默认的超时设置
默认是没有超时限制的,见SimpleClientHttpRequestFactory 类的
private int connectTimeout = -1; // -1 表示不超时
private int readTimeout = -1; // -1 表示不超时
代码设置超时时间
Application中或者@Configuration注解的类中配置:
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(10000); // 连接到主机 超时时间
factory.setReadTimeout(10000); // 从主机读取数据 超时时间
return factory;
}
配置文件设置超时时间
yml写法:
rest:
template:
conn:
connect-timeout: 3000
read-timeout: 3000
properties写法:
#restTemplate配置
rest.connection.connection-request-timeout=30000
rest.connection.connect-timeout=30000
rest.connection.read-timeout=30000
请求例子
配置了超时之后,启动项目,通过浏览器请求controller,发现无效,这是为什么呢?
当然无效。因为超时设置的从本项目请求其他项目。
controller中加个请求,通过restTemplate访问本项目中的延迟方法,发现超时有效了。
@ResponseBody
@RequestMapping("/request")
public String request(){
String url ="http://localhost:8080/timeout/demo1";
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
params.add("username", "用户名");
params.add("password", "123456");
restTemplate.postForEntity(url,params,String.class);
return "request success";
}
httpClient 1.3版本之前 的配置
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate restTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectionRequestTimeout(3 * 1000); // 从链接池获取连接的超时时间
httpRequestFactory.setConnectTimeout(3 * 1000); // 连接到主机超时
httpRequestFactory.setReadTimeout(3 * 1000); // 从主机读取数据超时
return new RestTemplate(httpRequestFactory);
}
}
httpClient 1.4版本之后的配置
@Configuration
public class AppConfig
{
@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder)
{
return restTemplateBuilder
.setConnectTimeout(3000)
.setReadTimeout(3000)
.build();
}
}
接口超时时间
properties配置:
spring.mvc.async.request-timeout=20000
代码配置:
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void configureAsyncSupport(final AsyncSupportConfigurer configurer) {
configurer.setDefaultTimeout(20000);
configurer.registerCallableInterceptors(timeoutInterceptor());
}
@Bean
public TimeoutCallableProcessingInterceptor timeoutInterceptor() {
return new TimeoutCallableProcessingInterceptor();
}
}
超时请求类代码(模拟超时)
别人访问该服务:
@RequestMapping(value="/customSleep",name="customSleep")
public String customSleep(int n) {
try {
logger.info("");
Thread.sleep(n*1000);
} catch (InterruptedException e) {
e.printStackTrace();
return "InterruptedException";
}
return "success";
}
其他
linux超过21秒就报超时
看日志,请求是在23-25秒之间。用postman是可以返回的,项目访问却会报超时。
这是因为linux默认请求超时时间21秒,会重试n次。
linux执行以下命令,设置下重试次数:
vim /etc/sysctl.conf # 编辑
net.ipv4.tcp_syn_retries = 6 # 次数是6 表示6*21 大约127秒
sysctl -p /etc/sysctl.conf # 加载设置(-p后如果不跟文件名,默认从 /etc/sysctl.conf文件加载)
nginx设置超时时间
在location中设置即可:
proxy_connect_timeout 60; # 连接到主机超时时间
proxy_read_timeout 300; # 从主机读取数据超时时间