2012-08-08 248 views
0

我已經構建了一個使用Tomcat的流式中繼服務器。通過Tomcat流式傳輸

簡單的想法是:一個客戶端執行POST,另一個客戶端執行GET。該Servlet產生一個線程並進行簡單的字節混洗,直到InputSteam(來自POST)爲空。完成後關閉/回答這兩個請求。一切都很好,它完美的工作,但:

Tomcat似乎重用請求對象,甚至是InputStream對象!每隔10個POST,InputStream就不能被讀取,因爲已經關閉。仔細看看日誌,我意識到使用完全相同的InputStream對象被先前的請求使用(並因此關閉)。原來即使是HttpServletRequest對象也完全一樣。

這是怎麼回事?爲什麼Tomcat重複使用明顯沒有被正確重置的對象?我已經用7.0.29和6.0.16版本試過了,同樣的事情。

+1

這種事情通常發生在請求完成後保留對資源的引用時。您是否在任何地方存儲對請求,響應或流的引用? – 2012-08-09 00:44:11

+0

我沒有緩存任何請求或響應對象,但事實證明,字節混排線程釋放InputStream對象有點太遲了(在請求已經返回之後),所以我認爲這是問題所在。雖然我同意永遠不要緩存這些對象,但Tomcat迴應如此糟糕的事實令人大失所望! – Daniel 2012-08-09 19:12:29

回答

0

由於這是一個資源管理問題(你有一個線程持有InputStream太長),你應該能夠解決這個問題:有servlet (或提交任務到Executor ...你使用任何Executor爲此,對吧?)等待線程完成(或Future完成)並釋放其資源。如果您將代碼發佈到您的byte-pump線程(以及servlet的相關部分),我可以告訴您如何改進它們。

+0

解決方案很簡單,難點在於識別問題,我只是爲每個Input/OutputStream使用一個小包裝器。線程只引用包裝器,而不直接引用流,我可以在請求返回之前簡單地清空包裝器內的引用(該背景線程現在停止洗牌,並且即將清理 - 這有時會太長時間)。 – Daniel 2012-08-11 19:41:46

0

更新:

原來,我產生了關閉線程(這顯然不得不輸入和OutputStreams參考)未及時釋放那些引用始終。謝謝,克里斯托弗,指針!

儘管我同意高速緩存這些對象是非常糟糕的做法,而且絕對不應該這樣做,但對於Tomcat確實對此做出如此糟糕的反應,實在令人失望。我希望更好的應用程序服務器的成熟...

+0

您*可以*禁用這些對象的重用。結果是Tomcat產生了更多的垃圾,並且由於額外的GC活動而導致性能下降。 – 2012-08-10 13:56:41

+0

有趣。我該如何禁用?在我的情況下,我只有很少的連接可以混洗大量數據,所以沒有太多的對象可以重複使用...... – Daniel 2012-08-11 19:44:37

+0

如果您禁用了這種重用,它會對您處理的每個請求的性能產生負面影響。 。不只是那些你保留對流的引用。 – 2012-08-12 19:24:26