2011-09-26 44 views
0

我有一個Java客戶機(在Windows XP上的1.6b17,通過Java webstart啓動),它使用TCP套接字通過ADSL連接查詢基於Java的服務器。客戶端套接字有一個超時設置(3000毫秒)。設置超時設置的套接字有時會在閱讀時失速

偶爾(到目前爲止,不能重現),客戶端在讀取來自服務器的響應時停頓。有幾百次安裝,大多數用戶大多數時間都沒有遇到這個問題。

的客戶端按照以下步驟每個請求創建一個新的socket:

  1. 創建一個新的套接字設置超時時間爲3000ms
  2. 提交請求(文字單行)
  3. 閱讀多行響應,當收到特殊的「消息結束」序列時(或空),關閉套接字

下面是一些(簡化的)代碼來說明:

socket = new Socket(host, port); 
socket.setSoTimeout(socketTimeout); 

out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); 
in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

socket.write(cmd); 

while (true) { 

    line = in.readLine(); 

    if (line == null) break; 

    if (line.equals("EOL")) break; 

    // Store line of text in an ArrayList 
}  

socket.close(); 

問題是,偶爾,在接收過程中,客戶端會暫停5分鐘,然後恢復,不需要任何干預。在此之後,應用程序將繼續執行,但不會有明顯的性能問題。

在服務器端登錄表明該操作大約需要150ms,儘管在關閉套接字之前採取了有關時間戳(我將嘗試解決這個問題)。

我的工作假設之一是,這不是由於網絡問題,否則,readLine會超時,這是一個有效的假設嗎?

這似乎不可能是垃圾收集相關。該應用程序有512MB分配給堆,而正在檢索的數據由大約1600行100個字符組成。我的期望是,如果與GC或內存泄漏有關的問題會導致性能的普遍下降,而不是我所看到的那種「粘性」行爲,這是正確的嗎?

任何建議的策略來解決這個問題將不勝感激。

感謝, 菲爾

+0

套接字是否在客戶端自己的線程中讀取? –

+0

這是在美國東部時間,不理想,但不是我現在可以改變的東西。 – PhilDin

+0

您是否曾嘗試通過設置客戶端並一次又一次地執行請求來重現問題? –

回答

2

我沒有看到你起牀到五分鐘的「暫停」。我只能想象你正在對數據包進行大量重試。你應該可以用wireshark看到這樣的東西。它可以給你一個線索,如果它還有其他的東西。在512 MB的堆

你的全GC暫停時間應爲大約0.5秒(約相當)


如果你有一個不可靠的連接使用的PrintWriter我不會建議。如果它得到一個IOException,它會設置一個標誌而不是拋出異常。如果你繼續使用它,它什麼都不做。

+0

謝謝,我沒有意識到這一點;我會看到關於消除它。你認爲這對上述問題有影響嗎?請記住,數據最終都會通過嗎? – PhilDin

+0

在Wireshark上的良好通話,我會放棄。謝謝。 – PhilDin

1

readLine()應超時。在任何平臺上從來沒有見過這樣做沒有用。也許你一次只能接收一個角色,間隔不到3秒。 Wireshark會告訴你。

或者當您正在閱讀線路時,也許服務器未在正確的位置發送換行符?