2015-09-28 66 views
1

我要消耗2級的服務,並希望有不同的超時。所以,我已經覆蓋了Spring的SimpleClientHttpRequestFactory並使用它從我的HttpDaoImpl春RestTemplate readtimeout財產不能正常工作 - 奇怪的問題

現在一切工作在一個環境中,但是完全相同的EAR在其他環境中不起作用,只有兩個環境的不同之處在於,我所連接的服務URL是一個負載平衡URL,而另一個則是非LB。問題在負載均衡的服務URL中。

問題是,每次httpReadTimeout正在生效或正在使用,但不是XYZHttpReadTimeout,即使我有條件地設置超時。

這是非常奇怪的問題,因爲一切都在一個ENV工作。而不是其他。直到現在,我對可能的根本原因的猜測是負載平衡的URL,但我仍然無法看到任何技術上的原因,因爲我的機器會在讀取超時後打開一個套接字並將其關閉。

我已經把記錄器在CustomClientHttpRequestFactory和驗證正在使用正確的值,但最終如預期在某種程度上讀取超時不工作。

CustomClientHttpRequestFactory.java

public class CustomClientHttpRequestFactory extends SimpleClientHttpRequestFactory{ 

    private Log logger = LogFactory.getLog(CustomClientHttpRequestFactory.class); 

    @Value("${httpRequest.readTimeoutInMilliseconds}") 
    private Integer httpRequestTimeout; 

    @Value("${httpRequest.connectionTimeoutInMilliseconds}") 
    private Integer httpReadTimeout; 

    @Value("${XYZ.httpRequest.readTimeoutInMilliseconds}") 
    private Integer XYZHttpRequestTimeout; 

    @Value("${XYZ.httpRequest.connectionTimeoutInMilliseconds}") 
    private Integer XYZHttpReadTimeout; 

    @Value("${sgw.XYZHttp.service.url}") 
    private String XYZSystemUrl; 


    /** 
    * Overriding the default and setting a separate read timeout and HTTP connection timeout values for XYZ transactions. 
    * 
    * @param uri 
    */ 
    public void setTimeoutProperties(URI uri){ 
     boolean isXYZTransaction = isXYZTransaction(uri); 
     Integer connectionTimeout = isXYZTransaction ? XYZHttpRequestTimeout : httpRequestTimeout; 
     Integer readTimeout = isXYZTransaction ? XYZHttpReadTimeout : httpReadTimeout; 
     logger.info("Setting " + connectionTimeout + " : " + readTimeout); 
     this.setReadTimeout(readTimeout); 
     this.setConnectTimeout(connectionTimeout); 
    } 

    private boolean isXYZTransaction(URI uri){ 
     try { 
      URI XYZUrl = new URI(XYZSystemUrl); 
      logger.info("################################### XYZ Debug"); 
      logger.info("XYZHttpRequestTimeout = " + XYZHttpRequestTimeout); 
      logger.info("XYZHttpReadTimeout = " + XYZHttpReadTimeout); 
      return XYZUrl.equals(uri); 
     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     return false; 
    } 
} 

HttpDaoImpl

CustomClientHttpRequestFactory httpRequestFactory = (CustomClientHttpRequestFactory) myAppUtils.getApplicationContext().getBean("httpRequestFactory"); 
    httpRequestFactory.setTimeoutProperties(lUri); 
    restTemplate.setRequestFactory(httpRequestFactory); 
    responseString = restTemplate.postForObject(lUri, requestString, String.class); 

XML配置

<bean id="httpRequestFactory" class="com.abc.xyz.customComponents.CustomClientHttpRequestFactory" scope="prototype"/> 

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> 
    <property name="messageConverters"> 
     <list> 
      <bean class="org.springframework.http.converter.StringHttpMessageConverter"> 
       <property name = "supportedMediaTypes"> 
        <list> 
         <value>text/xml;charset=UTF-8</value> 
        </list> 
       </property> 
      </bean> 
     </list> 
    </property> 
</bean> 

回答

2

最後,發現問題並使其工作。

根源:
Spring的RestTemplate默認使用org.springframework.http.client.SimpleClientHttpRequestFactory,它在多線程環境的情況下有問題。在多線程環境中使用SimpleClientHttpRequestFactory時,根據您的一些規則(在我們的案例中,基於URL或服務消耗的不同超時),會使用多個超時值集合,這會造成問題。

一個blog突出相同。

這是有道理的,因爲我在我的問題中談到的2個環境中的另一個區別是一個環境(其中一切都很好)始終有一個用戶,這意味着只有一個線程和另一個環境(我有問題)有許多併發用戶意味着多個線程。

解決方案:
使用org.springframework.http.client.CommonsClientHttpRequestFactory,這是在Spring版本3.0.6的org.springframework.http.client.ClientHttpRequestFactory提供另一種實現方式,並在多線程環境下運行良好。

如果Spring版本爲3.0+然後使用HttpComponentsClientHttpRequestFactory

+1

這是發生在我身上,即使我用我HttpComponentsClientHttpRequestFactory。發生在一個環境中,但不在另一個環境中。我有兩個restTemplates,每個都配置了自己的超時,1分鐘和其他3分鐘。我所看到的是超時是1分鐘的一切。 –

+0

我沒有嘗試'HttpComponentsClientHttpRequestFactory',但我知道它的工作與'org.springframework.http.client.CommonsClientHttpRequestFactory' – hagrawal

+0

沒關係,我找到了我的問題的原因。它實際上是一個前端apache httpd服務器,其超時設置爲1分鐘。謝謝@hagrawal。 –