Tomcat使用Java NIO处理并发缓慢的TCP客户端连接。

12

我的理解

没有使用NIO:
对于每个保持连接的请求,服务器将继续阻塞一个线程。

使用了NIO:
此连接器具有几个轮询线程,用于保持所有连接用户的连接活动,同时在有新的HTTP请求可用时调用工作线程。

现在: 如果我有一个简单的servlet向客户端(浏览器)返回一个100KB的字符串。

....
String HunderdKBString = "reallylongstring"
PrintWriter out = response.getWriter();
out.println(HunderdKBString);
....

如果一个带有1 KB连接的客户端连接,则需要大约100秒才能接收字符串。
那么Java线程会被阻塞大约100秒吗?

TCP缓冲区、Java OutputStreamWriter或其他缓冲区如何影响线程阻塞时间?

PS:在CentOS 7上使用apache-tomcat-8.0.24和Oracle JDK 1.7。

编辑:正如提到的,线程确实会被阻塞,并且缓冲区可以减少线程阻塞时间...如何通过使用这些缓冲区来优化Tomcat/OS以减少线程阻塞时间?

如何在生产环境中检测是否由于许多慢速连接客户端连接到Tomcat而使其线程饥饿?


@Codo 我们正在处理一个具有峰值负载行为的网站。突然间500个客户端可以连接,这可能会转化为500 *(浏览器中的4个TCP连接)= 2000 .. 是的,很多可能会很慢.. - Bhuvan
拥有2000个并行连接,最实际的解决方案是将Tomcat的工作线程数增加到2000(甚至更多)。如今的服务器应该能够轻松处理这么多线程。不过,您可能需要为Tomcat分配足够的内存。如果我们要谈论的是100,000个连接,情况就会不同了。 - Codo
另一个选择——如果您的响应不包含任何用户或会话特定数据,因此可以缓存——是将nginx作为Tomcat前面的缓存。nginx有选项立即消耗整个响应并以给定的慢速度将其转发给客户端。 - Codo
如果您的响应不可缓存,nginx甚至可能起作用。请查看使用缓冲区释放后端服务器 - Codo
看一下反向代理(apache,nginx)的功能。缓存、负载均衡... 您可以使用Java Mission Control工具监视您的tomcat。 - Beñat Bermejo
显示剩余3条评论
1个回答

2

那么Java线程会被阻塞大约100秒吗?

是的。

TCP缓冲区、Java OutputStream或Writer或其他缓冲区会如何影响线程阻塞时间?

如果缓冲区足够大以容纳发送的数据,则发送线程不会被阻塞。


请问您能否指向一些资源,教我如何优化Tomcat/操作系统,通过增加不同类型的缓冲区来减少线程阻塞时间? - Bhuvan
我不同意@EJP的第二个说法:缓冲区只有在操作系统级别才有帮助。在OutputStream或Writer类中的缓冲区是无效的,因为一旦Tomcat尝试刷新所有未完成的数据,它们仍然会阻塞。 - Codo
与其开始调整缓冲区,你应该将请求超时时间降低到可接受的水平。如果用户占用线程时间过长并导致饥饿现象,则及时终止这些用户的线程将解决你的问题。无论是用户引起的问题还是所提供的文件太大,操作系统方面可能很难进行优化。更仔细地查看服务器的配置。 - dieterh
@Codo 我的第二个陈述是正确的。我没有说缓冲区有任何“帮助”,从阻塞的角度来看,你谈论哪个缓冲区都没有区别。一旦所有缓冲区都满了,发送将被阻塞。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接