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

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

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

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

所以我的问题是,在Java中,基于proactor的IO处理是否可能以这样一种方式用于特定场景是有利的;而且,如果 Java NIO 确实支持基于 proactor 的 IO 处理(在 Java 6 或 Java 7 中),是否正在利用操作系统托管的异步 IO 支持(即来自操作系统的完成回调)?此外,如果实现纯粹在 VM 中实现,则性能优势非常小,以至于使用主动事件处理只能提供一种不同的(可能更简单的)方法来构造并发网络处理软件。

对于任何对主动事件处理感兴趣的人,这里都是一篇很好的文章,概述了优点/缺点,并与传统的每个连接线程和反应式IO模型进行了比较。


答案 1

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

在 Java 中,基于 proactor 的 IO 处理是否可行,以便用于特定方案。

Java 1.4 引入了非阻塞 IO,这与异步 IO 不同。Java SE 7 引入了带有 JSR203 的异步 IO,使“真正的”proactor 样式 IO 处理实现成为可能。

请参阅 AsyncrhonousSocketChannelAsynchronousServerSocketChannel

而且,如果 Java NIO 确实支持基于 proactor 的 IO 处理(在 Java 6 或 Java 7 中),是否正在利用操作系统托管的异步 IO 支持(即来自操作系统的完成回调)?

通读 JSR 203 规范,肯定支持使用新异步通道的完成处理程序,据报道,本机操作系统功能正在被利用,但我还没有确定在多大程度上。在分析了Java 7源代码之后,我可能会跟进这一点(除非有人打败我)。

此外,如果实现纯粹在 VM 中实现,则性能优势非常小,以至于使用主动事件处理只能提供一种不同的(可能更简单的)方法来构造并发网络处理软件。

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

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

国际海事组织似乎很明显,在许多情况下,反应堆/生产者使用更传统的方法使非常简单的设计复杂化,而在其他更复杂的系统中,它们提供了高度的简化和灵活性。

. . .

顺便说一句,我强烈建议您阅读以下关于NIO的演示文稿,该演示提供了NIO与“传统”方法之间的性能比较。虽然我也建议谨慎对待,因为基准测试中的NIO实现是基于Java 1.4之前的NBIO NIO库,而不是1.4中提供的NIO实现。


答案 2

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

没有要读取的数据的读取块。这可能是大多数时候。但是,当缓冲区已满时,写入阻塞很少发生,并且通常会导致连接缓慢或使用者失败。

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

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


推荐