2016-01-18 135 views
6

我有一個Spring Boot REST服務,有時會將第三方服務作爲請求的一部分來調用。我想設置所有資源的超時時間(比如說5秒),這樣如果任何請求處理(整個鏈,從傳入到響應)花費超過5秒鐘,我的控制器將響應HTTP 503而不是實際的響應。這將是真棒,如果這只是一個彈簧屬性,例如設置Spring Boot REST API - 請求超時?

spring.mvc.async.request-timeout=5000 

但我沒有任何運氣。我也嘗試過擴展WebMvcConfigurationSupport並重寫configureAsyncSupport:

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

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

沒有任何運氣。

我懷疑我必須手動計時所有第三方調用,如果它們花費太長時間,則會引發超時異常。是對的嗎?或者是否有更簡單,更全面的解決方案來涵蓋我的所有請求端點?

回答

9

你需要的,如果你想spring.mvc.async.request-timeout=5000向返回Callabe工作。

@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

如果使用Java 8,也可以用蘭巴表達式: 'return() - > {/ *在這裏做你的東西* /}'; – demaniak

2

如果你正在使用RestTemplate比你應該使用下面的代碼來實現超時

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

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

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

我建議你看看Spring Cloud Netflix Hystrix啓動器來處理潛在的不可靠/慢速的遠程調用。它實現了電路斷路器模式,這是專門用於這種事情。

請參閱offcial docs for more information

+1

我不明白爲什麼這是downvoted,它在我看來,執行電路斷路器模式是最好的答案。否則,只需在請求運行時返回503,就可能浪費資源 – Jeremie

0

你可以在你的application.properties中試試server.connection-timeout=5000。從official documentation:以毫秒爲單位

server.connection超時=#時間關閉連接之前該連接器將 等待另一HTTP請求。如果未設置 ,則將使用連接器的容器特定默認值。使用-1的 值表示無(即無限)超時。

在另一方面,你可能要處理上使用斷路器模式的客戶端超時,因爲我已經在我的答案已經在這裏描述:https://stackoverflow.com/a/44484579/2328781