Java I/O与Java新I/O(NIO)在Linux NPTL下的区别

22

我的Web服务器使用常规的Java I/O和每个连接一个线程的机制。现在,由于用户增加(长轮询),它们正处于困境中。但是,这些连接大多数情况下是空闲的。尽管可以通过添加更多Web服务器来解决此问题,但我一直在研究NIO实现。

我对此有着复杂的印象。我已经阅读了一些基准测试报告,在这些报告中,带有新NPTL库的常规I/O要优于NIO。

配置和使用最新的Linux NPTL与Java I/O的真实体验如何?是否有性能提升?

并且就更广泛的问题而言:

在标准服务器类机器(Dell四核心处理器)上,我们期望在(使用Linux NPTL库?)正常情况下执行的I/O和阻塞线程的最大数量是多少(我们在Tomcat线程池中进行配置)?如果线程池变得非常大,比如超过1000个线程,会有什么影响?

非常感谢提供任何参考和指针。


2
我认为如今1000以上的数量并不算“非常大”... - andersoj
3个回答

18

挑衅性的博客文章,"避免使用NIO,获得更好的吞吐量。" Paul Tyma在(2008)博客中声称可以轻松处理5000个线程而没有任何问题;我听说有人声称可以处理更多:

  1. 启用NPTL后,Sun和Blackwidow JVM 1.4.2很容易扩展到5000+个线程。阻塞模型始终比使用NIO选择器快25-35%。采用了EmberIO团队建议的许多技术——使用多个选择器,在第一个读取返回Java中的EAGAIN等效时进行多个(2个)读取。但是我们无法击败使用Linux NPTL的普通每个连接模型。
我认为关键在于测量开销和性能,只有当您知道需要并且可以证明改进时,才转向非阻塞I/O。编写和维护非阻塞代码所需的额外工作应纳入您的决策考虑范围内。我的看法是,如果您的应用程序可以使用同步/阻塞I/O清晰地表达,请这样做。如果您的应用程序适合使用非阻塞I/O,并且不会在应用空间中重新发明阻塞I/O,则考虑根据测量的性能需求移动到nio。我惊讶地发现,在Google搜索结果中,很少有资源引用任何(最近的)数字!

此外,请参见Paul Tyma的演示幻灯片:旧方法再次流行。基于他在Google的工作,具体数字表明,在Linux上,同步线程I/O非常可扩展,并且认为“NIO更快”是一个曾经正确但现在不再正确的神话。有一些关于Comet Daily的良好附加评论here on Comet Daily。他引用了以下(轶事性的,仍然没有实际基准测试链接等...)NPTL结果:

在测试中,NPTL成功地在两秒钟内启动了100,000个线程,在IA-32上进行。相比之下,在没有NPTL的内核下,这个测试需要大约15分钟。
如果您真的遇到了可扩展性问题,您可能希望使用XX:ThreadStackSize调整线程堆栈大小。因为您提到了Tomcat,请看这里
最后,如果您决心使用非阻塞I/O,请尽一切努力建立在由知道他们在做什么的人构建的现有框架之上。我浪费了太多时间试图正确地解决一个错综复杂的非阻塞I/O解决方案(出于错误的原因)。
另请参见相关SO问题

非常感谢您的评论。我并不愿意转移到NIO,因为使用它的好处并不是很高,而且代码复杂度相当大。这实际上就是这篇文章的初衷 :) - Sajid

4

我有点不愿意放弃旧的IO框架。我的查询意图是想看看是否有办法用NPTL来扩展典型的IO?这些链接非常有帮助,谢谢。 - Sajid
Node.js使用线程池(因此在Linux上使用NPTL)来执行阻塞系统调用。对于网络连接,它使用epoll。 - janneb

2

Sajid,我看到你正在进行Comet(长轮询)。

几乎没有人谈论在NIO中执行Comet事件的用户代码的问题。调度Comet事件的NIO线程调用您的代码,如果您的代码不够好,您将阻塞此关键线程,其他Comet连接必须等待,因为NIO线程正在执行类似于S.O.的线程调度程序的工作。这不是使用IO的Comet中的问题,因为线程仅用于您的Comet事件/任务,调度程序可以在想要时放弃您的线程(使用NIO方法不是那么容易)。

“同步Comet”(基于IO)唯一的问题是线程堆栈的内存消耗。


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