通过NIO连接器部署到Tomcat时是否使用Servlet 3.0异步冗余?

问题描述 投票:3回答:1

[我看到了这个线程:Java - Async in Servlet 3.0 vs NIO in Servlet 3.1,但它似乎与Servlet 3.1 NIO有关(与Tomcat NIO HTTP连接器相对。)。

据我了解,使用NIO HTTP连接器实现(Tomcat 8及更高版本中的默认设置)配置Tomcat来处理请求并产生响应的实际工作是在单独的工作线程上进行的,而轮询器线程则进行读写数据保持畅通。

这似乎是异步Servlet 3.0解决的同一问题,因为在请求/响应上完成的工作是在独立于http连接线程的工作线程上完成的。

那么,这两个解决方案是同一个问题吗?换句话说,如果servlet容器已经异步,以异步方式编写代码有什么好处?

tomcat servlet-3.0
1个回答
5
投票

通过了解从容器到应用程序代码的请求处理中不同点发生IO的潜在位置,可以更容易理解这一点。容器连接器(BIO / NIO)的工作是接受套接字连接并将其移交给线程,该线程有时会调用Servlet GET / POST方法。现在,Tomcat NIO连接器基本上是容器决定使用Java NIO工具(Selector / Channel)以更少的线程处理多个IO通道。 Selector提供了一种机制,用于监视一个或多个NIO通道并识别何时有一个或多个NIO通道可用于数据传输,因此使用选择器容器可以使用一个线程而不是多个线程来管理多个通道。这些就绪通道然后由数量可能少于BIO连接器所需数量的线程服务。

另外-在此级别上进行了OS级别的优化,以改善NIO的功能。例如,Java附带基于Linux epoll事件通知工具的java.nio.channels.SelectorProvider实现。 epoll功能在Linux 2.6和更高版本的内核中可用。当成千上万的SelectableChannels注册到Selector时,新的基于epoll的SelectorProvider实现比传统的基于轮询的SelectorProvider实现更具可伸缩性。当检测到2.6内核时,默认情况下将使用新的SelectorProvider实现。当检测到2.6之前的内核时,将使用基于轮询的SelectorProvider。

现在回到眼前的问题。在Servlet 3.0之前,整个Servlet处理都是同步的,这在Servet 3.0中得到了改进,因此GET / POST方法现在可以立即返回,但无需写入响应,除非通过调用AsyncContext complete认为已完成。到目前为止,一切都很好。但是还有另一个问题。 Servlet处理可能包括对请求中可用的输入流/输出流的读/写。此IO的性质仍然是传统的。 Servlet 3.0允许异步请求处理,但是IO读/写仍然是旧样式,例如,当以较低速度从客户端读取大请求有效负载时,线程将阻塞等待数据-因此Servlet 3.1非阻塞IO可以进行救援现在,只要数据准备就绪,您就可以对读/写逻辑进行回调样式的调用,而无需线程等待它。可以在代码中看到它的工作方式here

我们仍然必须记住,数据库IO(如果有)仍然是传统的等待IO。该区域由遵循JDBC API的数据库驱动程序控制,并且他们知道有朝一日他们也为非阻塞IO提供API。 Oracle已经在领导一项这样的计划Asynchronous Database Access,该计划也似乎正在利用Java NIO。这将为使整个请求处理成为非阻塞铺平道路。

[Spring还有另一项有希望的工作-Reactive relational database connectivity,旨在解决这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.