我看到了这个线程:Java-Servlet 3.0中的异步与Servlet 3.1中的NIO,但它似乎与Servlet 3.1 NIO有关(与Tomcat NIO HTTP连接器相对)。
据我了解,使用NIO HTTP连接器实现(在Tomcat 8及更高版本中为默认设置)配置Tomcat的实际工作是在单独的工作线程上完成处理请求并产生响应的工作,而轮询器线程则可读取/写入数据保持畅通。
这似乎与Async Servlet 3.0解决的问题相同,因为在请求/响应上完成的工作是在独立于http连接线程的工作线程上完成的。
那么,它们是针对同一问题的两种解决方案吗?换句话说,如果Servlet容器已经是异步的,以异步方式编写代码是否有任何好处?
通过了解从容器到应用程序代码的请求处理中不同点发生IO的潜在位置,可以更容易理解这一点。容器连接器(BIO / NIO)的工作是接受套接字连接并将其移交给线程,该线程在某个时间点调用Servlet GET / POST方法。现在,Tomcat NIO连接器基本上是容器决定使用Java NIO工具(Selector / Channel)来处理具有更少线程的多个IO通道。Selector
提供了一种机制来监视一个或多个NIO通道并识别何时有一个或多个NIO通道可用于数据传输,因此使用选择器容器可以使用一个线程而不是多个线程来管理多个通道。这些就绪通道然后由数量可能少于BIO连接器所需数量的线程服务。
顺便说一句-在此级别上进行了OS级别的优化,以改善NIO的功能。例如,Java附带了java.nio.channels.SelectorProvider
基于Linux epoll事件通知工具的实现。该epoll
功能在Linux 2.6和更高版本的内核中可用。当成千上万的Selector注册了SelectableChannel时,新的基于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阻止用于救援现在,只要数据准备好了,您就可以对读/写逻辑进行回调样式调用,而不必等待线程等待它。这在代码中如何工作可以在这里看到。
我们仍然必须记住,数据库IO(如果有)仍然是传统的等待IO。该区域由遵守JDBC API的数据库驱动程序控制,并且他们知道有一天他们也为非阻塞IO提供API。Oracle已经在领导这样的一项举措,即异步数据库访问,它也似乎正在利用Java NIO。这将为使整个请求处理成为非阻塞铺平道路。
Spring还进行了另一项有希望的工作-响应关系数据库连接,旨在解决此问题。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句