2016-01-18 19 views
6

Mam usługę REST usługi Spring Boot, która czasami wywołuje usługi stron trzecich jako część żądania. Chciałbym ustawić limit czasu dla wszystkich moich zasobów (powiedzmy 5 sekund), więc jeśli jakakolwiek obsługa żądań (cały łańcuch, od przychodzących do odpowiedzi) trwa dłużej niż 5 sekund, moje kontrolery odpowiadają za pomocą HTTP 503 zamiast rzeczywistej odpowiedzi . Byłoby świetnie, gdyby była to tylko własność Spring, na przykład ustawienieSpring Boot REST API - czas oczekiwania na żądanie?

spring.mvc.async.request-timeout=5000 

, ale nie miałem z tym szczęścia. Próbowałem również rozciągający WebMvcConfigurationSupport i przesłanianie configureAsyncSupport:

@Override 
public void configureAsyncSupport(final AsyncSupportConfigurer configurer) { 
    configurer.setDefaultTimeout(5000); 
    configurer.registerCallableInterceptors(timeoutInterceptor()); 
} 

@Bean 
public TimeoutCallableProcessingInterceptor timeoutInterceptor() { 
    return new TimeoutCallableProcessingInterceptor(); 
} 

bez powodzenia.

Podejrzewam, że muszę ręcznie wyrejestrować wszystkie połączenia z osobami trzecimi, a jeśli trwają zbyt długo, wyrzucić wyjątek limitu czasu. Czy to prawda? Czy istnieje jakieś łatwiejsze, całościowe rozwiązanie, które obejmuje wszystkie moje punkty końcowe żądania?

Odpowiedz

9

Trzeba zwrócić Callabe jeśli chcesz spring.mvc.async.request-timeout=5000 do praca.

@RequestMapping(method = RequestMethod.GET) 
public Callable<String> getFoobar() throws InterruptedException { 
    return new Callable<String>() { 
     @Override 
     public String call() throws Exception { 
      Thread.sleep(8000); //this will cause a timeout 
      return "foobar"; 
     } 
    }; 
} 
+3

W przypadku korzystania z Java 8, można również użyć wyrażenia Lamba: 'return() -> {/ * rób swoje rzeczy tutaj * /}'; – demaniak

2

jeśli używasz RestTemplate niż należy użyć następującego kodu do wdrożenia timeoutów

@Bean 
public RestTemplate restTemplate() { 
    return new RestTemplate(clientHttpRequestFactory()); 
} 

private ClientHttpRequestFactory clientHttpRequestFactory() { 
    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); 
    factory.setReadTimeout(2000); 
    factory.setConnectTimeout(2000); 
    return factory; 
}} 

Konfiguracja xml

<bean class="org.springframework.web.client.RestTemplate"> 
<constructor-arg> 
    <bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory" 
     p:readTimeout="2000" 
     p:connectTimeout="2000" /> 
</constructor-arg> 

1

Proponuję spojrzeć na rozruszniku Wiosna Chmura Netflix hystrix do obsługi potencjalnie nierzetelne/wolno połączeń zdalnych. Wprowadza wzór Circuit Breaker, który jest przeznaczony właśnie do tego rodzaju rzeczy.

Zobacz offcial docs for more information.

+1

Nie rozumiem, dlaczego zostało to odrzucone, wydaje mi się, że najlepszym rozwiązaniem jest wdrożenie wzoru wyłącznika. W przeciwnym razie, po prostu zwracając 503, pozostawiając żądanie uruchomione, prawdopodobnie marnujesz zasoby – Jeremie

0

Możesz spróbować server.connection-timeout=5000 w pliku application.properties. Z official documentation:

server.connection-timeout = # czas w milisekundach, że złącza będzie poczekać na kolejne żądania HTTP przed zamknięciem połączenia. Jeśli nie zostanie ustawiony, domyślnie zostanie użyte domyślne ustawienie kontenera. Użyj wartości wynoszącej -1, aby wskazać brak (tj. Nieskończony) limit czasu.

Z drugiej strony, może chcesz obsłużyć limity czasu po stronie klienta przy użyciu PRZERYWACZ wzór jak już opisane w moim odpowiedź tutaj: https://stackoverflow.com/a/44484579/2328781

Powiązane problemy