Весна RestTemplate ожидания


Я хотел бы установить время ожидания соединения для службы rest, используемой моим веб-приложением. Я использую Рестемплейт весны, чтобы поговорить со своей службой. Я провел некоторые исследования, и я нашел и использовал xml ниже (в моем приложении xml), который, как я считаю, предназначен для установки таймаута. Я использую Spring 3.0.

Я также видел ту же проблему здесь Настройка таймаута для spring webservices с RestTemplate но решения не кажутся такими чистыми , я бы предпочел установите значения таймаута через Spring config

<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>

Похоже, что бы я ни установил readTimeout, я получаю следующее:

Сетевой кабель отключен: Ждет около 20 секунд и сообщает следующее исключение:

Орг.весенняя рамка.сеть.клиент.Ного ResourceAccessExcep: ошибка ввода/вывода: нет маршрута к хосту: подключить; вложенные исключением является Java.чистая.NoRouteToHostException: нет маршрута к хосту: соединения

Url неверный so 404, возвращенный службой rest: Ждет около 10 секунд и сообщает следующее исключение:

Орг.весенняя рамка.сеть.клиент.HttpClientErrorException: 404 Не Найден

Мои требования требуют более коротких тайм-аутов, поэтому я должен быть в состоянии изменить их. Есть идеи насчет того, что я делаю не так?

Большое спасибо.

5 75

5 ответов:

Для Пружинного Ботинка >= 1.4

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

Для Пружинного Ботинка

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

    @Bean
    public RestTemplate customRestTemplate()
    {
        return new RestTemplate(customHttpRequestFactory());
    }
}

Тогда в вашем application.properties

custom.rest.connection.connection-request-timeout=...
custom.rest.connection.connect-timeout=...
custom.rest.connection.read-timeout=...

Это работает, потому что HttpComponentsClientHttpRequestFactory имеет открытые сеттеры 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);
    }
}

Наконец-то у меня получилось.

Я думаю, что тот факт, что наш проект имел две разные версии jar commons-httpclient, не помог. Как только я разобрался с этим, я обнаружил, что ты можешь делать две вещи...

В коде можно поставить следующее:

HttpComponentsClientHttpRequestFactory rf =
    (HttpComponentsClientHttpRequestFactory) restTemplate.getRequestFactory();
rf.setReadTimeout(1 * 1000);
rf.setConnectTimeout(1 * 1000);

При первом вызове этого кода будет установлен тайм-аут для класса 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>

Где я использую интерфейс RestOperations в своем коде и получаю значения таймаута из файла свойств.

Этот вопрос является первым звеном для поиска Spring Boot, поэтому было бы здорово поместить здесь Решение, рекомендованное в официальной документации . Spring Boot имеет свой собственный удобный боб RestTemplateBuilder:

@Bean
public RestTemplate restTemplate(
        RestTemplateBuilder restTemplateBuilder) {

    return restTemplateBuilder
            .setConnectTimeout(500)
            .setReadTimeout(500)
            .build();
}

Ручное создание экземпляров RestTemplate является потенциально трудным подходом, поскольку другие автоматически настроенные бобы не вводятся в созданные вручную экземпляры.

Вот действительно простой способ установить тайм-аут:

RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());

private ClientHttpRequestFactory getClientHttpRequestFactory() {
    int timeout = 5000;
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory =
      new HttpComponentsClientHttpRequestFactory();
    clientHttpRequestFactory.setConnectTimeout(timeout);
    return clientHttpRequestFactory;
}

У меня был похожий сценарий,но также требовалось установить прокси. Самый простой способ, который я мог видеть, чтобы сделать это, состоял в том, чтобы расширить SimpleClientHttpRequestFactory Для простоты установки прокси (различные прокси для non-prod vs prod). Это должно все еще работать, даже если вам не требуется прокси. Затем в моем расширенном классе я переопределяю Метод openConnection(URL url, Proxy proxy), используя то же самое, что и источник , но просто устанавливая таймауты перед возвращением.

@Override
protected HttpURLConnection openConnection(URL url, Proxy proxy) throws IOException {
    URLConnection urlConnection = proxy != null ? url.openConnection(proxy) : url.openConnection();
    Assert.isInstanceOf(HttpURLConnection.class, urlConnection);
    urlConnection.setConnectTimeout(5000);
    urlConnection.setReadTimeout(5000);
    return (HttpURLConnection) urlConnection;
}