直到现在,因为它适用于服务 http 请求,我认为这些术语 -asynchronous
并且non-blocking i/o
意味着同样的事情。但显然,它们已分别在 servlet 3.0 和 3.1 中分别实现。我很难理解这里的区别......
请问有人可以对这个话题有更多的了解吗?具体来说,我正在寻找一个示例,说明服务器的 servlet 3.0 实现如何异步,但在线程上阻塞?我认为如果我理解这一点,可能更容易理解 servlet 3.1 中的非阻塞 i/o 试图解决的确切问题。
直到现在,因为它适用于服务 http 请求,我认为这些术语 -asynchronous
并且non-blocking i/o
意味着同样的事情。但显然,它们已分别在 servlet 3.0 和 3.1 中分别实现。我很难理解这里的区别......
请问有人可以对这个话题有更多的了解吗?具体来说,我正在寻找一个示例,说明服务器的 servlet 3.0 实现如何异步,但在线程上阻塞?我认为如果我理解这一点,可能更容易理解 servlet 3.1 中的非阻塞 i/o 试图解决的确切问题。
我会尝试总结我学到的东西。要理解 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 中,有两种情况需要考虑:
ServletOutputStream
很慢,则客户端线程必须等待。在这两种情况下,执行传统 I/O(用于请求/响应)的服务器线程都会阻塞。换句话说,在 Servlet 3.0 中,只有请求处理部分变为异步的,而用于处理请求和响应的 I/O 则没有。如果有足够多的线程阻塞,这会导致线程饥饿并影响性能。
ReadListener
使用 Servlet 3.1 NIO ,这个问题通过WriteListener
接口解决了。这些在ServletInputStream
和中注册ServletOutputStream
。侦听器具有回调方法,当内容可供读取或写入时调用,而 servlet 容器不会阻塞 I/O 线程。因此,这些 I/O 线程被释放,现在可以为其他请求提供服务,从而提高性能。
(有关更多信息,请参阅链接 2。)
学分