32

直到现在,因为它适用于服务 http 请求,我认为这些术语 -asynchronous并且non-blocking i/o意味着同样的事情。但显然,它们已分别在 servlet 3.0 和 3.1 中分别实现。我很难理解这里的区别......

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

4

1 回答 1

59

我会尝试总结我学到的东西。要理解 Servlet 3.0 和 Servlet 3.1 解决的问题,我们这样看:

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

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

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

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

在传统的 I/O 中,有两种情况需要考虑:

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

换句话说,在 Servlet 3.0 中,只有请求处理部分变为异步的,而用于处理请求和响应的 I/O 则没有。如果有足够多的线程阻塞,这会导致线程饥饿并影响性能。

ReadListener使用 Servlet 3.1 NIO ,这个问题通过WriteListener接口解决了。这些在ServletInputStream和中注册ServletOutputStream。侦听器具有回调方法,当内容可供读取或写入时调用,而 servlet 容器不会阻塞 I/O 线程。因此,这些 I/O 线程被释放,现在可以为其他请求提供服务,从而提高性能。 (有关更多信息,请参阅链接 2。

学分

于 2016-10-25T04:16:57.040 回答