2013-04-10 56 views
1

我在Tomcat上運行Web應用程序。我的應用程序與其他Web服務建立連接以滿足來自客戶端的請求。有時我在打開URL連接時得到了java.net.UnknownHostException,然後有時候我開始得到java.net.SocketException:打開的文件過多。而我的服務器停止進一步接受連接。請指導。java.net.UnknownHostException和java.net.SocketException:打開的文件太多

String response; 
    HttpURLConnection conn = null; 
BufferedReader rd = null; 
InputStream in = null; 
try 
{ 
    // Send data 
    String urlStr = URL; 
    URL url = new URL(urlStr); 
    conn = (HttpURLConnection)url.openConnection(); 
    conn.setRequestProperty("content-type", "application/x-www-form-urlencoded"); 
    int contentLength = conn.getContentLength(); 
    // System.out.println("content length 1" + contentLength); 
    if (contentLength <= 0) 
    { 
     InputStream in1 = (conn).getErrorStream(); 
     if (in1 != null) 
     { 
      in1.close(); 
     } 
     conn.getInputStream().close(); 
     in = null; 
     conn.disconnect(); 
     conn = null; 
     return null; 
    } 
    in = conn.getInputStream(); 
    if (conn.getResponseCode() != 200) 
    { 
     InputStream in1 = (conn).getErrorStream(); 
     if (in1 != null) 
     { 
      in1.close(); 
     } 
     conn.getInputStream().close(); 
     in = null; 
     conn.disconnect(); 
     conn = null; 
     in.close(); 
     in = null; 
     return null; 
    } 
    // Get the response 
    rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
    StringBuffer stringBuffer = new StringBuffer(); 
    String line = null; 
    while ((line = rd.readLine()) != null) 
    { 
     stringBuffer.append(line); 
    } 
    response = stringBuffer.toString(); 
    System.out.println("full ads response = " + response); 
} 
catch (Exception ex) 
{ 
    // ex.printStackTrace(); 
} 
finally 
{ 
    try 
    { 
     if (conn != null) 
     { 
      InputStream in1 = (conn).getErrorStream(); 
      if (in1 != null) 
      { 
       in1.close(); 
      } 
      conn.getInputStream().close(); 
      in = null; 
      conn.disconnect(); 
      conn = null; 
     } 
     if (rd != null) 
     { 
      rd.close(); 
      rd = null; 
     } 
     if (in != null) 
     { 
      in.close(); 
      in = null; 
     } 
    } 
    catch (Exception e) 
    { 
    } 
} 
return null;   

回答

0

嘗試增加你的linux服務器打開文件的限制來修復java.net.SocketException: Too many open files。馬克斯文件大小限制爲存儲在該文件在Linux中:

/proc/sys/fs/file-max 

檢查打開的文件在當前的時間,你可以使用:

lsof 

檢查沒有。打開文件,使用:

lsof | wc -l 

另外,除了conn.disconnect()之外,關閉你的連接conn.close()。確保你也關閉了inputreader。所有這種關閉應該最終阻止,以便在發生任何異常情況時連接也被關閉。

+0

Hello Ankit。我已經設定了最大值,這就是爲什麼需要一些才能達到這個極限。我的服務器git 5000客戶端請求每分鐘和每個請求打開服務器上的URL連接來從其他Web服務獲取一些數據。 – 2013-04-10 05:35:57

+0

@YasirPerwez:請注意我給出的其他建議,確保您在完成工作後關閉了連接和輸入流。 – Ankit 2013-04-10 05:56:11

+0

我會肯定的。清理我的代碼並嘗試。將更新這個結果。謝謝 – 2013-04-10 06:24:44

0

你在windows或linux上運行嗎?檢查這篇文章,希望它有幫助:http://edmund.haselwanter.com/en/blog/2009/03/13/tomcat-too-many-open-files/

+0

你好馬丁,我正在使用Linux,我已經增加了最大限度。但是在java.net.UnknownHostException之後它似乎泄漏了套接字並將它釋放到下一個GC。我僅在堆棧流中發現了這一點,但我錯過了該鏈接。我在linux上運行Java 1.7,Tomcat 7。 – 2013-04-10 05:33:57

2

UnknownHostException只是意味着您使用的URL指的是一個不存在的主機名,或可能是主機名的DNS記錄或系統在該瞬間過渡。

套接字泄漏可能是由您的過多清理代碼引起的,請參閱註釋。

當你壓制所有異常時,你不希望在冥王星發現哪裏出了問題。所以這是第一個要解決的問題。永遠不要忽略異常記錄它們。打印他們的堆棧痕跡。做一點事。

但是你的代碼有許多其他的問題:

HttpURLConnection conn = null; 
BufferedReader rd = null; 
InputStream in = null; 
try 
{ 
    // Send data 
    String urlStr = URL; 

這個變量是多餘的。下面只需使用URL

URL url = new URL(urlStr); 
    conn = (HttpURLConnection)url.openConnection(); 
    conn.setRequestProperty("content-type", "application/x-www-form-urlencoded"); 

目前爲止確定。

int contentLength = conn.getContentLength(); 
    // System.out.println("content length 1" + contentLength); 
    if (contentLength <= 0) 

檢查零內容長度是非常不尋常的。這是檢查錯誤的代理嗎?我會簡單地刪除這個測試。

{ 
     InputStream in1 = (conn).getErrorStream(); 
     if (in1 != null) 
     { 
      in1.close(); 
     } 
     conn.getInputStream().close(); 
     in = null; 
     conn.disconnect(); 
     conn = null; 
     return null; 
    } 

以上所有內容都是多餘的。你已經在finally塊中擁有它了。去掉它。

in = conn.getInputStream(); 
    if (conn.getResponseCode() != 200) 

現在就是如何檢查錯誤。但是,您必須先致電getResponseCode(),然後您致電getInputStream(),,否則後者可能會拋出FileNotFoundException,因爲您可能更感興趣響應代碼爲404。

{ 
     InputStream in1 = (conn).getErrorStream(); 
     if (in1 != null) 
     { 
      in1.close(); 
     } 
     conn.getInputStream().close(); 
     in = null; 
     conn.disconnect(); 
     conn = null; 
     in.close(); 
     in = null; 
     return null; 
    } 

同樣,以上所有都是多餘的。你已經在finally塊中擁有它了。去掉它。

// Get the response 
    rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
    StringBuffer stringBuffer = new StringBuffer(); 
    String line = null; 

line的初始化是多餘的。該變量在下一行中分配。去掉它。

while ((line = rd.readLine()) != null) 
    { 
     stringBuffer.append(line); 
    } 
    response = stringBuffer.toString(); 
    System.out.println("full ads response = " + response); 
} 
catch (Exception ex) 

您應該只在這裏捕獲IOException

{ 
    // ex.printStackTrace(); 

決不忽略一個例外。

} 
finally 
{ 
    try 
    { 
     if (conn != null) 
     { 
      InputStream in1 = (conn).getErrorStream(); 
      if (in1 != null) 
      { 
       in1.close(); 
      } 

您不需要獲取或關閉錯誤流。刪除所有這些。

  conn.getInputStream().close(); 
      in = null; 

將此變量設置爲null毫無意義。這是一個局部變量,所以它無論如何都將會超出範圍。

  conn.disconnect(); 
      conn = null; 

同上。

 } 
     if (rd != null) 
     { 
      rd.close(); 
      rd = null; 
     } 

您已關閉輸入流。這是多餘的。刪除此塊。

 if (in != null) 
     { 
      in.close(); 
      in = null; 
     } 

您已關閉連接的輸入流。這全是多餘的。去掉它。

} 
    catch (Exception e) 
    { 
    } 

同樣,你應該只在這裏捕IOException,你不應該被忽略的錯誤。就我個人而言,我會有拋出IOException的方法,並且根本沒有任何catch塊。返回null對調用者不是很有用。他通常會更清楚地知道出了什麼問題,所以他可以做出有用的決定,以便對此做些什麼。

} 
return null;   
+1

+1描述性答案:) – Ankit 2013-04-10 05:56:45

+0

嗨EJP,謝謝你這樣的細節。我非常欣賞這一努力。 – 2013-04-10 06:06:04

+0

爲了解決類似問題的不同解決方案,我在快速解決這個bug方面做得很糟糕。 (我知道這是一個蹩腳的藉口:))我一定會清理它。但是當它被清理時,錯誤就在那裏。關於啓用打印堆棧,我最近對它進行了評論,只是爲了讓我的日誌文件更小,否則它只是使stdout.log的大小變得巨大。 – 2013-04-10 06:17:51

相關問題