2011-07-11 210 views
3

我在CXF 2.2.5中使用JAX-RS支持來調用REST Web服務。我爲每個需要與之通信的端點(通常是任何給定部署的一個或兩個端點)創建一個org.apache.cxf.jaxrs.client.WebClient實例,併爲每個Web服務調用重新使用此客戶端。CXF JAXRS客戶端不重用TCP連接

我面臨的問題是客戶端正在爲每個請求創建到服務器的新TCP連接,儘管使用了保持活動設置。在高流量水平,這是造成問題。下面摘錄了我的客戶代碼。

我試圖挖掘CXF源來發現問題,但目前正在失望。任何想法不勝感激。

感謝, FB

ConcurrentMap<String, WebClient> webclients = new ConcurrentHashMap<String, WebClient>(); 

public void dispatchRequest(MyRequestClass request, String hostAddress) { 

    // Fetch or create the web client if we don't already have one for this hostAddress 
    // NOTE: WebClient is only thread-safe if not changing the URI or headers between calls! 
    // http://cxf.apache.org/docs/jax-rs-client-api.html#JAX-RSClientAPI-ThreadSafety 
    WebClient client = webclients.get(hostAddress); 
    if (client == null) { 
     String serviceUrl = APP_HTTP_PROTOCOL + "://" + hostAddress + ":" + APP_PORT + "/" + APP_REQUEST_PATH; 
     WebClient newClient = WebClient.create(serviceUrl).accept(MediaType.TEXT_PLAIN); 
     client = webclients.putIfAbsent(hostAddress, newClient); 
     if (client == null) { 
      client = newClient; 
     } // Else, another thread must have added the client in the meantime - that's fine if so. 
    } 

    XStream marshaller = MyCollection.getMarshaller(); 
    String requestXML = marshaller.toXML(request); 

    Response response = null; 
    try { 
     // Send it! 
     response = client.post(requestXML); 
    } 
    catch (Exception e) { 
    } 

    ... 
} 

回答

4

在示例代碼中你會得到一個JAX-RS響應,這getEntity()方法將默認返回的InputStream。因此,CXF不負責消費流,這顯然是開放的。

如果你沒有明確地關閉它,它會在垃圾收集階段關閉。 即使如此,在高流量速率下,這個小延遲可以防止底層HTTP連接重新插入由HttpURLConnection(CXF在發動機罩下使用)所利用的持久連接的內部池中。所以它不能按時重用。

如果你注意關閉InputStream,你不應該再看到大量的TIME_WAIT套接字。

+1

感謝agoware,這很有道理,在此期間,我最終貶低爲基本的公共Http連接方式,因爲我的要求很容易制定,而且我幾乎不需要真正做任何事情,如果我再次使用CXF,這肯定會有用! –

1

我肯定會嘗試更新到CXF的更新和支持的版本。在更新版本的CXF中,JAX-RS的內容已經有很多更新,這個問題可能已經被修復了。

+0

我很喜歡,但由於我的控制範圍之外有一些更廣泛的項目依賴關係,所以我現在堅持使用這個版本。 :-( –

+0

丹,我試着在我的開發機器上升級到2.4.1,但不幸遇到了同樣的問題 –