我将尝试总结我所学到的知识。要了解 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 对象中,以实现回调方法。
(有关详细信息,请参阅链接 1。Runnable
AsyncContext
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 线程被释放出来,现在可以为其他提高性能的请求提供服务。(有关详细信息,请参阅链接 2。ReadListener
WriteListener
ServletInputStream
ServletOutputStream
学分