Java Non-Blocking and Asynchronous IO with NIO & NIO.2 (JSR203) - Reactor/Proactor 实现

Posted

技术标签:

【中文标题】Java Non-Blocking and Asynchronous IO with NIO & NIO.2 (JSR203) - Reactor/Proactor 实现【英文标题】:Java Non-Blocking and Asynchronous IO with NIO & NIO.2 (JSR203) - Reactor/Proactor Implementations 【发布时间】:2011-07-28 14:23:27 【问题描述】:

所以我在这里阅读我最喜欢的软件模式书籍之一(面向模式的软件架构 - 并发和网络对象的模式),特别是关于 Proactor/Reactor 异步 IO 模式的部分。我可以看到通过使用可选通道,我可以很容易地实现 Reactor 风格的异步 IO 机制(并且已经这样做了)。但是,我看不到如何使用非阻塞写入实现适当的 Proactor 机制。这是利用操作系统管理的非阻塞写入功能。

操作系统特定调用支持的功能,如 win32 下的GetQueuedCompletionStatus。

我确实看到 Java 7 通过异步完成处理程序为 NIO 带来了一些更新(这似乎是正确的方向)。话虽这么说......鉴于缺乏对操作系统管理的异步操作(特别是异步写入)的统一跨平台支持,我假设这是一个未利用本机操作系统支持的准实现。

所以我的问题是,在 Java 中基于前摄器的 IO 处理是否可能在特定场景中使用是有利的?并且,如果 Java NIO 确实支持基于前摄器的 IO 处理(在 Java 6 或 Java 7 中),是否正在使用操作系统管理的异步 IO 支持(即来自操作系统的完成回调)?此外,如果实现纯粹是在虚拟机中,那么性能优势就会很小,以至于使用主动事件处理只能提供一种不同(可能更简单)的方式来构建并发网络处理软件。

适用于任何对主动事件处理感兴趣的人here is a good article,其中概述了优缺点以及与传统的每连接线程和反应式 IO 模型的比较。

【问题讨论】:

如果你真的想知道它的实现是什么样的,那么你可以下载JDK 7的源代码并自己看看:openjdk.java.net/projects/jdk7 好点杰斯珀。我会尽快努力做到这一点! 【参考方案1】:

NIO 已经提供了响应式模式(选择器)和NIO2 adds an implementation of the proactive pattern(完成处理程序)的实现。

不要重新发明它,只需使用它,因为你无法超越它的性能 - 毕竟这是任何试图避免阻塞 i/o 的人 - 使用纯 Java 解决方案,因为你无法访问底层操作系统的非阻塞/异步特性。但是 NIO 和 NIO2 使用了这些,这使得它们速度很快。

【讨论】:

@EJP 我完全同意你的回答,只是想添加一些肉(我刚刚发现 - 所以我不会忘记)。 @EJP OT:我单击了您个人资料中的 telekinesis.com.au 链接,试图找出您个人资料中的“音乐家”的全部内容,但是……链接已失效!不过,它仍然存在于回程机器中,而您的简历告诉了我一切,而且比我想知道的还要多。我希望它的 health 部分不必修改。 wayback in 2007 你将其描述为:Excellent general health; excellent fitness; non-smoker. 如果我不住在亚洲以北几英里的地方,我很想喝杯啤酒。【参考方案2】:

这其中涉及很多因素。我将尝试尽可能地总结我的发现(意识到关于反应器和前摄器 IO 处理实现的有用性存在争议的事实)。

基于前摄器的 IO 处理是否可行 在 Java 中,它是 有利于用于特定 场景。

Java 1.4 引入了与异步 IO 不同的非阻塞 IO。 Java SE 7 引入了带有 JSR203 的异步 IO,使得“真正的”前摄器风格的 IO 处理实现成为可能。

见AsyncrhonousSocketChannel、AsynchronousServerSocketChannel

并且,如果 Java NIO 确实支持前摄器 基于 IO 处理(在 Java 6 或 Java 7) 是操作系统管理的异步 IO 支持(即完成回调 来自操作系统)正在使用?

通读 JSR 203 规范,肯定支持使用新的异步通道的完成处理程序,据报道正在使用本机操作系统功能,但我尚未确定在何种程度上。在分析 Java 7 源代码后,我可能会跟进此问题(除非有人击败我)。

此外,如果实施是 纯粹在虚拟机中是性能 好处如此之少以至于使用 主动事件处理优惠 只不过是不同的 (可能更简单)的构建方式 并发网络处理软件。

我无法找到有关 Java 7 中新的异步 IO 功能的任何性能比较。我相信它们将在不久的将来推出。

与往常一样,当出现解决问题的方法不止一种时,关于哪种方法更好的问题几乎总是用“取决于”来回答。主动事件处理(使用异步完成处理程序)包含在 Java 7 中,不能没有目的就简单地存在。对于某些应用程序,使用这种 IO 处理是有意义的。从历史上看,proactor 具有良好适用性的一个常见示例是在 HTTP 服务器中频繁发出许多短请求。更深入的解释give this a read(提供只是为了突出前摄器的优点,所以尽量忽略示例代码是 C++ 的事实)。

IMO 似乎很明显,在许多情况下,反应器/前导器使使用更传统方法的非常简单的设计变得复杂,而在其他更复杂的系统中,它们提供了高度的简化和灵活性。

。 . .

在旁注中,我强烈建议阅读the following presentation about NIO,它提供了 NIO 和“传统”方法之间的性能比较。尽管我也建议谨慎对待呈现的结果,因为基准测试中的 NIO 实现基于 Java 1.4 之前的 NBIO NIO 库,而不是 1.4 中发布的 NIO 实现。

【讨论】:

我在尝试在 java 中找到与 boost::asio 相当的东西时遇到了这个问题。我的结论是,现在什么都不存在,但 Java7 可能会出现类似的情况。 作为更新:Java 1.4 NIO 在 Windows select 上使用,Java 7 AIO 在 Windows IOCP 上使用,所以在 Windows AIO 上肯定更快,更具可扩展性。【参考方案3】:

我最喜欢的软件模式之一 书籍(面向模式的软件 架构 - 并发模式 和网络对象)

这本书已经过时并且在任何时候都具有可疑的相关性。它源于 1990 年代后期的设计模式***,当时人们齐心协力地将整个计算机科学简化为设计模式。

我现在的观点是,NIO 已经是一个框架和设计模式了。

【讨论】:

IMO 它已经过时了。非阻塞 IO 是许多工程师害怕或忘记的事情。这本书展示了一个在 C++ 中为 NIO 设计的可靠设计,该设计在今天很强大(Boost/ACE 有前摄器和反应器实现)。冒着听起来像模式贩子的风险,reactor 和类似 proactor 的 IO 处理是每个工程师都应该知道的(尤其是 reactor)。 @S73417H:除此之外,NIO 源于 select(),它源于每个进程的单个线程。现在有一种思想流派说,现在我们有了线程,我们根本不需要非阻塞/多路复用 I/O。在尝试实现基于 Reactor 的通用 NIO 框架后,我不得不强烈反对这是每个工程师都应该知道的事情。 NIO 与 Reactor 的斗争如此之多,以至于您别无选择,只能坚持 NIO。在我看来,围绕 NIO 的框架(例如 Mina)不能作为反例。 @EJP...我不得不恭敬地不同意你的观点。抛开性能不谈,通用 NIO 框架当然可以更好地分离网络代码中的关注点。根据我的经验,如果你很好地理解和使用这些框架,开发人员可以创建更易于理解、灵活和可测试的网络应用程序。此外,我看不出蔚来汽车和反应堆是如何相互对抗的。我发现使用 Java NIO 实现反应器非常简单。此外,在数以千计的并发网络连接可以随时处于活动状态的情况下,使用 reactor 的线程池表现出色。 @S73417H:用 NIO 实现 Reactor 很简单。困难的是在此之上构建一个通用框架。我自己的尝试和其他人(例如米娜)的尝试都不会鼓励我。 Peter Lawrey 已在此处或 Oracle Java 论坛上发布了一项研究的结果,这反驳了您的最后观点。【参考方案4】:

我会检查你是否真的需要担心阻塞写入。

没有数据可读取的读取块。这可能是大部分时间。但是,当缓冲区已满时写入会阻塞,这种情况很少发生,通常表示连接缓慢或消费者失败。

如果您想要非阻塞 IO,请为读取执行此操作,并为写入执行此操作。

注意:将阻塞 IO 与 NIO 一起使用通常更简单,并且可以执行非阻塞 NIO,除非您有 1000 个连接,否则您可能会发现添加的复杂性不值得。 (而且可能不是最好的选择)

【讨论】:

同意对于大多数解决方案,基于反应器的 IO 处理机制是最合适的。但在某些情况下,主动 IO 处理是有利的(特别是利用底层操作系统提供的抢占式多核线程)。所以我想我的问题与是否需要前摄器或者它在任何特定场景中是否具有优势并没有真正的关系,而是可以用 Java 成功地完成它而不是毫无意义的。 我怀疑它没有用的主要原因是,当您将阻塞 NIO 与非阻塞 NIO 进行比较时,您可以通过高达 1000 个连接的阻塞(每个连接一个线程)IO 获得显着更好的性能。我没有在 Windows 上测试过这个,但是我认为你应该假设可能没有任何性能改进。

以上是关于Java Non-Blocking and Asynchronous IO with NIO & NIO.2 (JSR203) - Reactor/Proactor 实现的主要内容,如果未能解决你的问题,请参考以下文章

Java NIO (10) Non-blocking Server

Java NIO学习笔记七 Non-blocking Server

Java NIO: Non-blocking Server 非阻塞网络服务器

asy CLI

PHP Php - DÃasy mesesenespañol

blocking cache和non-blocking cache