在Java中监视和查杀被阻止的线程

时间:2011-08-16 09:41:17

标签: java multithreading tomcat6

在我正在编写的基于servlet的应用程序中,我们为读者和编写者提供了单独的线程类。使用LinkedBlockingQueue<byte[]>将数据从写入器传输到多个读取器,因此如果没有新的数据可以从写入器获取,则读者可以安全地阻止。问题是,如果这些读取器线程所服务的远程客户端终止连接,Tomcat将不会抛出损坏的管道,除非编写器发送新数据并尝试将此新块传输到远程客户端。换句话说,可以对我们的服务执行以下攻击:

  1. 启动流式写入请求,不要向其写入任何数据。
  2. 继续创建和删除读取连接。由于编写器不生成任何数据,因此附加到它的读取线程仍然被阻塞并占用内存和其他资源。
  3. 观察服务器快速耗尽RAM。
  4. 我是否应该创建一个单独的维护线程来监控属于被阻止的读取器线程的套接字,并将interrupt()发送给那些似乎已失去与各自客户端连接的那些线程?上述架构中是否存在任何重大缺陷?谢谢。

2 个答案:

答案 0 :(得分:3)

听起来我的漏洞在于你的读者永远等待,无论传入连接的状态如何(当然,你无法知道)。

因此,如果合适,解决此问题的直接方法是使用BlockingQueue上的poll方法,而不是take。调用poll可以指定超时,如果没有数据添加到队列,读者将返回null

通过这种方式,读者不会永远被阻止,并且应该相对快速地回到正常的处理循环中,允许他们的资源被适当地释放。

(当然,这不是灵丹妙药;虽然超时仍在运行,但读者会消耗资源。但最终,资源有限的服务器会对DDOS攻击产生一些漏洞 - 这会降低其对可定制的影响小窗口,而不是让你的服务器永久残废,至少。)

答案 1 :(得分:0)

我过去采用的方法是阻塞连接,只有读取器线程。如果要写入多个连接,可以在当前线程中执行此操作。如果您担心每个写入阻塞,您可以使用一个监视线程来关闭被阻止的连接。

您仍然可以将资源绑定在未使用的套接字中,但我会有另一个线程找到未使用的套接字并关闭它们。

这使得每个连接只需一个线程,再加上几个监控线程。