Java - Servlet 3.0 中的 Async 与 Servlet 3.1 中的 NIO

2022-09-01 07:28:25

到目前为止,由于它适用于提供http请求,我认为这些术语 - 并且意味着同样的事情。但显然,它们分别在 servlet 3.0 和 3.1 中单独实现。我正在努力理解这里的区别...asynchronousnon-blocking i/o

有人可以更多地了解这个话题吗?具体来说,我正在寻找一个示例,说明服务器的 servlet 3.0 实现如何异步,但在线程上阻塞?我想如果我理解了这一点,可能更容易理解servlet 3.1中的非阻塞i / o试图解决的确切问题。


答案 1

我将尝试总结我所学到的知识。要了解 Servlet 3.0 和 Servlet 3.1 解决的问题,让我们这样看一下:

在Servlet 3.0之前:
同步处理请求的问题在于,在响应发出之前,它会导致线程(执行繁重的工作)运行很长时间。如果这种情况大规模发生,servlet 容器最终会耗尽线程 - 长时间运行的线程会导致线程匮乏。

在 Servlet 3.0 之前,对于这些长时间运行的线程,有特定于容器的解决方案,我们可以在其中生成一个单独的工作线程来执行繁重的任务,然后将响应返回给客户端。启动工作线程后,servlet 线程返回到 servlet 池。Tomcat的Comet,WebLogic的FutureResponseServlet和WebSphere的Aightal Request Dispatcher是异步处理实现的一些例子。
(有关详细信息,请参阅链接 1

Servlet 3.0 异步:
实际工作可以委托给线程池实现(独立于特定于容器的解决方案)。该实现将执行实际处理,并将使用 将请求分派到另一个资源或写入响应。我们还可以将 AsyncListener 实现添加到 AsyncContext 对象中,以实现回调方法。
(有关详细信息,请参阅链接 1RunnableAsyncContext

Servlet 3.1 NIO:
如上所述,Servlet 3.0 允许异步请求处理,但只允许传统的 I/O(与 NIO 相反)。为什么传统的 I/O 是一个问题?

在传统 I/O 中,需要考虑两种方案:

  • 如果进入服务器 (I/O) 的数据阻塞或流式传输速度比服务器读取速度慢,则尝试读取此数据的服务器线程必须等待该数据。
  • 另一方面,如果来自写入的服务器的响应数据很慢,则客户端线程必须等待。在这两种情况下,执行传统 I/O(对于请求/响应)的服务器线程都会阻塞。ServletOutputStream

换句话说,在 Servlet 3.0 中,只有请求处理部分成为异步,而不是用于为请求和响应提供服务的 I/O。如果有足够的线程阻塞,这会导致线程匮乏并影响性能。

使用Servlet 3.1 NIO,这个问题可以通过接口来解决。这些已在 和 中注册。侦听器具有回调方法,这些回调方法在内容可供读取时调用,或者可以在不使 servlet 容器阻塞 I/O 线程的情况下写入这些方法。因此,这些 I/O 线程被释放出来,现在可以为其他提高性能的请求提供服务。(有关详细信息,请参阅链接 2ReadListenerWriteListenerServletInputStreamServletOutputStream

学分


答案 2

推荐