【问题标题】:Java - Async in Servlet 3.0 vs NIO in Servlet 3.1Java - Servlet 3.0 中的异步与 Servlet 3.1 中的 NIO
【发布时间】:2017-02-09 16:31:27
【问题描述】:

直到现在,当它适用于服务 http 请求时,我认为这两个术语 - asynchronousnon-blocking i/o 意思相同。但显然,它们已分别在 servlet 3.0 和 3.1 中分别实现。我很难理解这里的区别......

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

【问题讨论】:

    标签: java servlets servlet-3.0 servlet-3.1


    【解决方案1】:

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

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

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

    Servlet 3.0 异步:
    实际工作可以委托给线程池实现(独立于容器特定的解决方案)。 Runnable 实现将执行实际处理并将使用AsyncContext 将请求分派到另一个资源或写入响应。我们还可以将 AsyncListener 实现添加到 AsyncContext 对象以实现回调方法。
    (有关详细信息,请参阅 link 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 则没有。如果有足够多的线程阻塞,则会导致线程不足并影响性能。

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

    学分

    【讨论】:

    • 但在现实世界的普通应用程序中,我无法想象服务器写入响应速度很慢。它要么有来自控制器的完整响应(如 json 响应字符串),要么没有。通过将 NGINX 放在应用服务器前面,可以缓解慢速客户端。那么我们为什么要关心这个 3.1 呢?我也怀疑慢客户端是真实的论点 - 如果您使用非阻塞套接字(如非阻塞 Tomcat 连接器),您将尽可能多地从每个客户端读取而不会阻塞。再说一遍,为什么是 3.1?
    猜你喜欢
    • 2013-11-16
    • 1970-01-01
    • 2011-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-27
    相关资源
    最近更新 更多