2012-08-08 180 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