Spring RestTemplate zaman aşımı


125

Web uygulamam tarafından kullanılan bir dinlenme servisi için bağlantı zaman aşımlarını ayarlamak istiyorum. Servisimle konuşmak için Spring's RestTemplate kullanıyorum. Biraz araştırma yaptım ve aşağıdaki xml'yi buldum ve kullandım (xml uygulamamda) ki bunun zaman aşımını ayarlamak olduğuna inanıyorum. Spring 3.0 kullanıyorum.

Aynı sorunu burada da gördüm RestTemplate ile bahar web hizmetleri için zaman aşımı yapılandırması ancak çözümler o kadar temiz görünmüyor , zaman aşımı değerlerini Spring yapılandırması aracılığıyla ayarlamayı tercih ederim

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

Görünüşe göre readTimeout'u ne ayarlasam aşağıdakileri alıyorum:

Ağ kablosunun bağlantısı kesildi: Yaklaşık 20 saniye bekler ve aşağıdaki istisnayı bildirir:

org.springframework.web.client.ResourceAccessException: G / Ç hatası: Ana bilgisayara yol yok: bağlan; iç içe geçmiş istisna java.net.NoRouteToHostException: Barındırma yolu yok: bağlan

Url hatalı, bu nedenle 404 dinlenme hizmeti tarafından döndü: Yaklaşık 10 saniye bekler ve istisnayı bildirir:

org.springframework.web.client.HttpClientErrorException: 404 Bulunamadı

Gereksinimlerim daha kısa zaman aşımları gerektirdiğinden bunları değiştirebilmem gerekiyor. Neyi yanlış yaptığıma dair bir fikrin var mı?

Çok teşekkürler.

Yanıtlar:


164

İçin Yay Boot> 1.4 =

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

İçin 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());
    }
}

sonra senin içinde application.properties

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

Bunun nedeni çalışır HttpComponentsClientHttpRequestFactorykamu ayarlayıcılar vardır connectionRequestTimeout, connectTimeoutve readTimeoutve @ConfigurationPropertiessizin için setler onları.


İçin Bahar Boot olmadan Bahar 4.1 veya Bahar 5 kullanılarak @ConfigurationyerineXML

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

        return new RestTemplate(httpRequestFactory);
    }
}

Güzel örnek! Lütfen örnekteki garip newifadeyi kaldırınSpring Boot
StasKolodyuk

7
Bu yapılandırmadan sonra, RestTemplate'in apache http istemcisini kullanacağını unutmayın (zaman aşımını ayarlamak için). Apache http istemci bağlantı havuzunun varsayılan maxPerRoute evreleri 5 ve maksimum toplam evreler 10'dur (httpClient-4.5.2). Bunu bazı durumlarda kendimiz ayarlamamız gerekir (örneğin birçok ana bilgisayara bağlanmamız ve daha fazla bağlantıya ihtiyacımız olması gibi).
bluearrow

2
Lütfen connectionRequestTimeoutözniteliğin 4.1.4'ten önce mevcut olmadığını unutmayın. YAYIN
Taoufik Mohdit

Spring Boot> = 1.4 yapılandırmasını Spring Boot> = 2.1.8 üzerinde denedim ve başarılı olamadım. Bu yapılandırmayı yapmak için bu yazıyı ( zetcode.com/springboot/resttemplate ) takip ettim .
Ângelo Polotto

@ ÂngeloPolotto gönderdiğiniz bağlantı bu çözümle aynı tavsiyeyi veriyor. Makalede şöyle diyor: "Alternatif olarak, işi yapmak için RestTemplateBuilder'ı kullanabiliriz."
dustin.schultz

76

Sonunda bunu çalıştırdım.

Bence projemizde commons-httpclient jar'ın iki farklı versiyonu olması yardımcı olmadı. Bunu çözdüğümde iki şey yapabileceğinizi öğrendim ...

Kodda aşağıdakileri yazabilirsiniz:

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

Bu kod ilk kez çağrıldığında, HttpComponentsClientHttpRequestFactorytarafından kullanılan sınıf için zaman aşımını ayarlayacaktır RestTemplate. Bu nedenle, tarafından yapılan sonraki tüm çağrılar RestTemplateyukarıda tanımlanan zaman aşımı ayarlarını kullanacaktır.

Ya da daha iyi seçenek bunu yapmaktır:

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

RestOperationsArayüzü kodumda kullandığım ve bir özellikler dosyasından zaman aşımı değerlerini aldığım yer.


Bu, bu dinlenme şablonu (bir tekil olan) aracılığıyla tüm aramalar için zaman aşımını ayarlar. İstek başına zaman aşımlarını kontrol etmenin mümkün olup olmadığını biliyor musunuz? (örneğin: bir posta araması için 10 saniye ve bir arama için 5 saniye vb.)
codesalsa

@ sardo. RestOperations arayüzünü kodumda kullandığım yer. bunun için herhangi bir açık arayüz oluşturmamız gerekiyor mu?
19'da çıkmaz

Benim de takılıp kaldığım Spring 3.0'ı kullandığınızı söylediniz, ancak 3.0'da HttpComponentsClientHttpRequestFactory yok! Bahar'ı güncellediniz mi?
Kutzi

5
Yukarıdaki kod en son İlkbaharda çalışmaz. ClassCastException verirjava.lang.ClassCastException: org.springframework.http.client.InterceptingClientHttpRequestFactory cannot be cast to org.springframework.http.client.HttpComponentsClientHttpRequestFactory
comiventor

41

Bu soru, Spring Boot araması için ilk bağlantıdır, bu nedenle, resmi belgelerde önerilen çözümü buraya koymak harika olur . Spring Boot'un kendi kullanışlı fasulye RestTemplateBuilder'ı vardır :

@Bean
public RestTemplate restTemplate(
        RestTemplateBuilder restTemplateBuilder) {

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

RestTemplate örneklerinin manuel olarak oluşturulması, potansiyel olarak zahmetli bir yaklaşımdır, çünkü diğer otomatik yapılandırılmış çekirdekler manuel olarak oluşturulan örneklere enjekte edilmemektedir.


2
Benim gibi Bahar'a yeni gelenler için bir not: Bunu bir @Configuration'a yapıştırmak hiçbir şey yapmaz. Bu yöntem, RestTemplateXhrTransport yapıcısına argüman olarak kullanan ve SocksJSClient'inize ilettiğiniz Taşıma Listenize ekleyeceğiniz bu RestTemplate'in bir yere enjekte edilmesini gerektirir.
Key Lay

setConnectTimeoutve bazı uygulamaları setReadTimeoutkullanımdan kaldırıldı
skryvets

17

İşte benim 2 sentim. Yeni bir şey değil, bazı açıklamalar, iyileştirmeler ve daha yeni kod.

Varsayılan olarak RestTemplatesonsuz zaman aşımına sahiptir. İki tür zaman aşımı vardır: bağlantı zaman aşımı ve okuma zaman aşımı. Örneğin sunucuya bağlanabiliyordum ama verileri okuyamadım. Uygulama asılıydı ve neler olduğu hakkında hiçbir fikrin yok.

Bugünlerde XML yerine tercih edilen ek açıklamaları kullanacağım.

@Configuration
public class AppConfig {

    @Bean
    public RestTemplate restTemplate() {

        var factory = new SimpleClientHttpRequestFactory();

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

        return new RestTemplate(factory);
    }
}

Burada SimpleClientHttpRequestFactorybağlantıyı ayarlamak ve zaman aşımlarını okumak için kullanıyoruz. Daha sonra yapıcısına aktarılır RestTemplate.

@Configuration
public class AppConfig {

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {

        return builder
                .setConnectTimeout(Duration.ofMillis(3000))
                .setReadTimeout(Duration.ofMillis(3000))
                .build();
    }
}

İkinci çözümde RestTemplateBuilder. Ayrıca iki yöntemin parametrelerine dikkat edin: alırlar Duration. Doğrudan milisaniyeler süren aşırı yüklenmiş yöntemler artık kullanımdan kaldırılmıştır.

Düzenleme Bahar Boot 2.1.0 ve Java 11 ile test edilmiştir.


Hangi yay ve java sürümünü kullanıyorsunuz?
orirab

2
Spring Boot 2.1.0 ve Java 11. Çalışan bir örnek için eğiticime bakabilirsiniz: zetcode.com/springboot/resttemplate
Jan Bodnar

Bunu yanıta eklemenizi öneririm
orirab


Teşekkürler @ JanBodnar, öğreticiniz Spring Boot 5.x
Ângelo Polotto

15

Zaman aşımını ayarlamanın gerçekten basit bir yolu:

RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());

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

0

Benzer bir senaryom vardı, ancak bir Proxy ayarlamam da gerekiyordu. Bunu yapmanın görebildiğim en basit yolu SimpleClientHttpRequestFactory, proxy'yi ayarlama kolaylığı için genişletmekti (üretim dışı ve üretim dışı için farklı proxy'ler). Proxy'ye ihtiyaç duymasanız bile bu yine de çalışmalıdır. Daha sonra genişletilmiş sınıfımda openConnection(URL url, Proxy proxy)yöntemi geçersiz kılıyorum , kaynakla aynı şeyi kullanarak , ancak geri dönmeden önce zaman aşımlarını ayarlıyorum.

@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;
}

0

Benscabbia'nın cevabını genişletmek için :

private RestTemplate restCaller = new RestTemplate(getClientHttpRequestFactory());

private ClientHttpRequestFactory getClientHttpRequestFactory() {
    int connectionTimeout = 5000; // milliseconds
    int socketTimeout = 10000; // milliseconds
    RequestConfig config = RequestConfig.custom()
      .setConnectTimeout(connectionTimeout)
      .setConnectionRequestTimeout(connectionTimeout)
      .setSocketTimeout(socketTimeout)
      .build();
    CloseableHttpClient client = HttpClientBuilder
      .create()
      .setDefaultRequestConfig(config)
      .build();
    return new HttpComponentsClientHttpRequestFactory(client);
}

0
  1. SimpleClientHttpRequestFactory ile RestTemplate zaman aşımı Zaman aşımı özelliklerini programlı olarak geçersiz kılmak için SimpleClientHttpRequestFactory sınıfını aşağıdaki gibi özelleştirebiliriz.

SimpleClientHttpRequestFactory ile zaman aşımını geçersiz kılın

//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;
}
  1. HttpComponentsClientHttpRequestFactory SimpleClientHttpRequestFactory ile RestTemplate zaman aşımı zaman aşımı ayarlamada yardımcı olur, ancak işlevsellik açısından çok sınırlıdır ve gerçek zamanlı uygulamalarda yeterli olmayabilir. Üretim kodunda, HTTP İstemci kitaplığını ve yeniden şablonunu destekleyen HttpComponentsClientHttpRequestFactory'yi kullanmak isteyebiliriz.

HTTPClient, bağlantı havuzu, boşta bağlantı yönetimi vb. Gibi diğer yararlı özellikleri sağlar.

Daha Fazla Oku: Spring RestTemplate + HttpClient yapılandırma örneği

HttpComponentsClientHttpRequestFactory ile zaman aşımını geçersiz kılın

//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;
}

başvuru: Spring RestTemplate zaman aşımı yapılandırma örneği

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.