Spring RestTemplate超时

sar*_*rdo 104 rest spring timeout resttemplate

我想为我的Web应用程序使用的休息服务设置连接超时.我正在使用Spring的RestTemplate与我的服务交谈.我做了一些研究,我发现并使用了下面的xml(在我的应用程序xml中),我认为这是为了设置超时.我正在使用Spring 3.0.

我也看到了同样的问题这里使用RestTemplate的spring webservices的超时配置,但解决方案看起来不干净,我更喜欢通过Spring配置设置超时值

<bean id="RestOperations" class="org.springframework.web.client.RestTemplate">
    <constructor-arg>

      <bean class="org.springframework.http.client.CommonsClientHttpRequestFactory">
        <property name="readTimeout" value="${restURL.connectionTimeout}" />
      </bean>
    </constructor-arg>
</bean>
Run Code Online (Sandbox Code Playgroud)

似乎无论我设置readTimeout是什么,我得到以下内容:

网络电缆断开连接: 等待大约20秒并报告以下异常:

org.springframework.web.client.ResourceAccessExcep tion:I/O错误:无主机路由:connect; 嵌套异常是java.net.NoRouteToHostException:没有到host的路由:connect

网址不正确,因此休息服务返回404: 等待大约10秒并报告以下异常:

org.springframework.web.client.HttpClientErrorException:404 Not Found

我的要求需要更短的超时时间,所以我需要能够更改这些.关于我做错了什么的任何想法?

非常感谢.

dus*_*ltz 145

对于Spring Boot> = 1.4

@Configuration
public class AppConfig
{
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) 
    {
        return restTemplateBuilder
           .setConnectTimeout(...)
           .setReadTimeout(...)
           .build();
    }
}
Run Code Online (Sandbox Code Playgroud)

对于Spring Boot <= 1.3

@Configuration
public class AppConfig
{
    @Bean
    @ConfigurationProperties(prefix = "custom.rest.connection")
    public HttpComponentsClientHttpRequestFactory customHttpRequestFactory() 
    {
        return new HttpComponentsClientHttpRequestFactory();
    }

    @Bean
    public RestTemplate customRestTemplate()
    {
        return new RestTemplate(customHttpRequestFactory());
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的 application.properties

custom.rest.connection.connection-request-timeout=...
custom.rest.connection.connect-timeout=...
custom.rest.connection.read-timeout=...
Run Code Online (Sandbox Code Playgroud)

这工作,因为HttpComponentsClientHttpRequestFactory有公共setter方法connectionRequestTimeout,connectTimeout以及readTimeout@ConfigurationProperties设置它们.


对于春季4.1或5春春不开机使用@Configuration,而不是XML

@Configuration
public class AppConfig
{
    @Bean
    public RestTemplate customRestTemplate()
    {
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectionRequestTimeout(...);
        httpRequestFactory.setConnectTimeout(...);
        httpRequestFactory.setReadTimeout(...);

        return new RestTemplate(httpRequestFactory);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,在此配置之后,RestTemplate将使用apache http client(设置超时).Apache http客户端连接池的默认maxPerRoute线程为5,最大总线程数为10(httpClient-4.5.2).我们需要在某些情况下自己设置(例如我们需要连接到许多主机并需要更多连接). (6认同)
  • 请注意,在4.1.4.RELEASE之前,`connectionRequestTimeout`属性不可用 (2认同)

sar*_*rdo 71

我终于搞定了这个.

我认为我们的项目有两个不同版本的commons-httpclient jar这一事实没有帮助.一旦我整理出来,我发现你可以做两件事......

在代码中,您可以输入以下内容:

HttpComponentsClientHttpRequestFactory rf =
    (HttpComponentsClientHttpRequestFactory) restTemplate.getRequestFactory();
rf.setReadTimeout(1 * 1000);
rf.setConnectTimeout(1 * 1000);
Run Code Online (Sandbox Code Playgroud)

第一次调用此代码时,它将为HttpComponentsClientHttpRequestFactory该类使用的类设置超时RestTemplate.因此,所有后续调用RestTemplate将使用上面定义的超时设置.

或者更好的选择是这样做:

<bean id="RestOperations" class="org.springframework.web.client.RestTemplate">
    <constructor-arg>
        <bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
            <property name="readTimeout" value="${application.urlReadTimeout}" />
            <property name="connectTimeout" value="${application.urlConnectionTimeout}" />
        </bean>
    </constructor-arg>
</bean>
Run Code Online (Sandbox Code Playgroud)

RestOperations在代码中使用接口并从属性文件中获取超时值的位置.

  • 上面的代码在最新的Spring中不起作用.它给出了ClassCastException`java.lang.ClassCastException:org.springframework.http.client.InterceptingClientHttpRequestFactory无法强制转换为org.springframework.http.client.HttpComponentsClientHttpRequestFactory` (4认同)
  • 因此,这设置了通过此休息模板(这是一个单例)的所有调用的超时。您知道是否可以控制每个请求的超时?(例如:post 调用 10 秒,get 调用 5 秒等) (2认同)

hel*_*dev 28

这个问题是Spring Boot搜索的第一个链接,因此,很高兴在这里提供官方文档中推荐解决方案.Spring Boot有自己的便利bean RestTemplateBuilder:

@Bean
public RestTemplate restTemplate(
        RestTemplateBuilder restTemplateBuilder) {

    return restTemplateBuilder
            .setConnectTimeout(Duration.ofSeconds(500))
            .setReadTimeout(Duration.ofSeconds(500))
            .build();
}
Run Code Online (Sandbox Code Playgroud)

手动创建RestTemplate实例是一种潜在的麻烦方法,因为其他自动配置的bean不会在手动创建的实例中注入.

  • 给像我这样的 Spring 新手的注意事项:只是将它放在 @Configuration 中不会做任何事情。此方法要求您将此 RestTemplate 注入某个地方,并将其用作 RestTemplateXhrTransport 构造函数的参数,您将依次将其添加到传递给 SocksJSClient 的传输列表中。 (2认同)

ben*_*bia 13

这是设置超时的一种非常简单的方法:

RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());

private ClientHttpRequestFactory getClientHttpRequestFactory() {
    int timeout = 5000;
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory =
      new HttpComponentsClientHttpRequestFactory();
    clientHttpRequestFactory.setConnectTimeout(timeout);
    return clientHttpRequestFactory;
}
Run Code Online (Sandbox Code Playgroud)


Jan*_*nar 10

这是我的2美分。没什么新鲜的,但是有一些解释,改进和更新的代码。

默认情况下,RestTemplate具有无限超时。超时有两种:连接超时和读取超时。例如,我可以连接到服务器,但无法读取数据。该应用程序已挂起,您不知道发生了什么。

我将使用批注,如今,批注已超过XML。

@Configuration
public class AppConfig {

    @Bean
    public RestTemplate restTemplate() {

        var factory = new SimpleClientHttpRequestFactory();

        factory.setConnectTimeout(3000);
        factory.setReadTimeout(3000);

        return new RestTemplate(factory);
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们用于SimpleClientHttpRequestFactory设置连接和读取超时。然后将其传递给的构造函数RestTemplate

@Configuration
public class AppConfig {

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {

        return builder
                .setConnectTimeout(Duration.ofMillis(3000))
                .setReadTimeout(Duration.ofMillis(3000))
                .build();
    }
}
Run Code Online (Sandbox Code Playgroud)

在第二个解决方案中,我们使用RestTemplateBuilder。还要注意两种方法的参数:它们采用Duration。现在不建议直接使用毫秒的重载方法。

编辑 使用Spring Boot 2.1.0和Java 11测试过。

  • Spring Boot 2.1.0和Java11。作为一个工作示例,您可以看一下我的教程:http://zetcode.com/springboot/resttemplate/ (2认同)

Zgp*_*ace 5

  1. 使用 SimpleClientHttpRequestFactory 的 RestTemplate 超时 为了以编程方式覆盖超时属性,我们可以自定义 SimpleClientHttpRequestFactory 类,如下所示。

使用 SimpleClientHttpRequestFactory 覆盖超时

//Create resttemplate
RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());

//Override timeouts in request factory
private SimpleClientHttpRequestFactory getClientHttpRequestFactory() 
{
    SimpleClientHttpRequestFactory clientHttpRequestFactory
                      = new SimpleClientHttpRequestFactory();
    //Connect timeout
    clientHttpRequestFactory.setConnectTimeout(10_000);

    //Read timeout
    clientHttpRequestFactory.setReadTimeout(10_000);
    return clientHttpRequestFactory;
}
Run Code Online (Sandbox Code Playgroud)
  1. RestTemplate 超时与 HttpComponentsClientHttpRequestFactory SimpleClientHttpRequestFactory 有助于设置超时,但它的功能非常有限,在实时应用程序中可能不够用。在生产代码中,我们可能希望使用支持 HTTP 客户端库和 resttemplate 的 HttpComponentsClientHttpRequestFactory。

HTTPClient 提供了其他有用的功能,例如连接池、空闲连接管理等。

阅读更多:Spring RestTemplate + HttpClient 配置示例

使用 HttpComponentsClientHttpRequestFactory 覆盖超时

//Create resttemplate
RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());

//Override timeouts in request factory
private SimpleClientHttpRequestFactory getClientHttpRequestFactory() 
{
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory
                      = new HttpComponentsClientHttpRequestFactory();
    //Connect timeout
    clientHttpRequestFactory.setConnectTimeout(10_000);

    //Read timeout
    clientHttpRequestFactory.setReadTimeout(10_000);
    return clientHttpRequestFactory;
}
Run Code Online (Sandbox Code Playgroud)

参考:Spring RestTemplate 超时配置示例


San*_*nth 5

SpringBoot版本>2

RestTemplate的简单超时。我将读写超时设置为3秒。

@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder){
        RestTemplate restTemplate= restTemplateBuilder.setConnectTimeout(Duration.ofMillis(3000)).setReadTimeout(Duration.ofMillis(3000)).build();
        return restTemplate;

}
Run Code Online (Sandbox Code Playgroud)

如果要设置动态超时值。请参考下文。

    //basic imports
    @SpringBootApplication
    public class DemoApplication{
    //the below values are injected from application.properties file
    @Value($"{connection.timeout.value}")
    private String connectionTimeoutValue;
    @Value("${read.timeout.value}")
    private String readTimeOutValue;
    
    public static void main(String args[]){
    
    SpringApplication.run(DemoApplication.class, args)
    }
    
        @Bean
        public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder){
                RestTemplate restTemplate= restTemplateBuilder.setConnectTimeout(Duration.ofMillis(connectionTimeoutValue)).setReadTimeout(Duration.ofMillis(readTimeOutValue)).build();
                return restTemplate;
        
        }
    
    }
Run Code Online (Sandbox Code Playgroud)

在 application.properties 文件内:

#change the numerical values according to your need.
connection.timeout.value=3000
read.timeout.value=3000
Run Code Online (Sandbox Code Playgroud)

注意:超时值以毫秒为单位。

对于 SpringBoot 版本<2:请删除 Duration.ofMillis 并直接提供值,如下所示...

RestTemplate restTemplate= restTemplateBuilder.setConnectTimeout(3000).setReadTimeout(3000).build();
Run Code Online (Sandbox Code Playgroud)