2014-03-18 84 views
1

我使用從的Java HTTPGET,在服務錯誤打開的文件太多

進口org.apache.http.client.methods.HttpGet REST式HTTPGET服務;

我創建了一個函數來查詢另一臺計算機上的服務。該電話工作正常,但我遇到了「太多打開文件」的服務。我的方面只是返回一個500錯誤,我發現。

我跟供應商談過了,他們非常堅定地認爲RESTful呼叫應該以持續的方式進行,並且我根本沒有釋放某些東西,並繼續說問題出在我身上。

我寫了一個壓力函數,見下文,以幫助隔離問題。據我所知,我釋放了一切。我對Java仍然很陌生,所以我只是沒有看到一些不清楚的東西。

import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.methods.CloseableHttpResponse; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.impl.client.CloseableHttpClient; 
import org.apache.http.impl.client.HttpClients; 

public void doStressTest() 
{ 
    String strUri = "http://<ip address>:<port>/task?vara=dataa&varb=datab"; 
    HttpGet oRestyGet = new HttpGet(); 
    oRestyGet.addHeader("Accept", "application/xml"); 

    for (int iLoop = 0; iLoop < 1000; iLoop++) 
    { 
     CloseableHttpClient httpclient = HttpClients.createDefault(); 
     try 
     { 
      oRestyGet.setURI(new URI(strUri)); 
      try 
      { 
       CloseableHttpResponse response2 = httpclient.execute(oRestyGet); 
       try 
       { 
        String strResponseHeader = response2.getStatusLine().toString(); 
        if (false == "HTTP/1.1 200 OK".equalsIgnoreCase(strResponseHeader)) 
         return; 

        continue; 
       } 
       finally 
       { 
        response2.close(); 
       } 
      } 
      catch (ClientProtocolException e) 
      { 
       e.printStackTrace(); 
      } 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
     finally 
     { 
      try 
      { 
       httpclient.close(); 
      } 
      catch (Exception e) 
      { 
       e.printStackTrace(); 
      } 
     } 
    } 

    try 
    { 
     oRestyGet.releaseConnection(); 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
} 

更新: 我以爲我想補充的廠商不得不說的文本,以防萬一這可能幫助。我應該補充一點,在下面的壓力測試中,我打開了一個HTTP GET請求對象,這對我的「會話」是持久的,並用於整個請求。

這意味着系統正在運行FDs,爲用戶運行 的過程。當開放式套接字或FD太多時會發生這種情況。 通常對於HTTP,強烈建議HTTP請求是以持久方式發送的 ,也就是說,您有一個用於整個會話的HTTP連接,並且不會爲每個請求打開多個HTTP連接,然後關閉 這些連接。更多的時候,你不會結束揮之不去的 連接。

我正在關閉「可關閉」的CloseableHttpClient,我也不認爲我需要只有一個。我應該補充一點,「我」並沒有耗盡任何東西,服務是。該供應商似乎認爲該服務與OS一樣是完美的。還能做些什麼來隔離問題?

更新2: (我把日誌文件從服務供應商,他們有下面要說的膠着狀態。?)

它看起來像問題是,有太多的連接通過您的界面打開 。我通過Firefox的 包含了一個會話的日誌文件。您可以看到如何使用瀏覽器通過同一連接發出多個HTTP請求。

只有一個線,其中初始連接時從[127.0.0.1] ...允許

隨後的GET請求是來自同一連接

HTTP連接。

...您的日誌文件顯示:HTTP從[192.168.20.123] ...允許

連接每個GET請求你讓着,這些連接都沒有關閉。

UPDATE 3: 我有權訪問服務生成的日誌,但無法訪問源。 Java的問題的連接,並響應於行GET請求作爲一個包:

我發出httpclient.close(),它不產生日誌條目,所以我懷疑是服務根本沒有響應對此。

由於我不熟悉另一端的機制,可能服務只是響應事件,問題在於CENTOS未正確處理close()調用。無論哪種方式,使用這種方法,問題不是我的。證明這是另一回事。另一種選擇是某種其他解決方案,可以正確地釋放資源。

+0

您是否嘗試過使用持久性/流水線HTTP 1.1連接? –

+0

我不確定那是什麼或代碼將如何改變。 –

回答

0

湯姆G爲正的事響應,問題是在供應商方面,但我創造了另一個答案的原因是,雖然廠商沒有關閉已打開的文件句柄,應力測試仍然墜毀。

我不得不切換到Jersey,它解決了每個GET請求執行打開/關閉操作的「httpclient.execute()」,然後供應商不得不給我一個構建來解決問題,因此有兩個問題。

apache框架似乎有問題,至少在我的實現中,而Sun框架(澤西島)在我的壓力測試中工作得很好。

現在我需要用真實的代碼進行測試。

1

如果你得到一個HTTP 500 Internal Server Error,那就有沒有什麼與你的客戶端代碼有關,或者你如何管理HTTP連接。問題完全在供應商方面。

+0

我同意你的看法,但是會推遲接受這個答案,問題出在廠商方面。我應該也可以創建/銷燬HTTP GET請求對象,但是噢,好吧,只需要一個。上面的壓力測試代碼看起來很完整,應該可以工作。是否有替代解決方案是另一個話題。我將嘗試捕獲日誌併發送給供應商。 –

+0

在服務/操作系統用完文件描述符(FD)之前,問題就出現了。問題在於釋放連接,一旦創建,就不會發生。我檢查了可用的屬性,並且僅從httpclient關閉(),我稱之爲。 httpclient可能有問題。很大程度上取決於我的呼叫下方的圖層工程。 –

0

我會使用lsof來查看哪些文件正在被打開。你也可以看看netstat -n -a來查看所有打開的連接。你有沒有嘗試過打開文件限制,看看你是否可以解決這個問題?

Too many open files (ulimit already changed)

+0

我不知道lsof命令。謝謝。 lsof命令顯示1006行看起來相似的行。這些是我的壓力測試要求。該服務在1007轟炸,這是正確的。 「netstat -n -a」沒有顯示我看到的任何有趣的東西。整個命令的輸出總數是512,所以沒問題。我假設列表FD,這與供應商說的相符。我如何處理這些信息? –

+0

我沒有碰到打開的文件限制,將不得不研究如何,但那不會有什麼好處,因爲問題稍後會發生。一個請求等於一個文件句柄保持打開狀態,直到關閉服務或重新啓動操作系統。 –

相關問題