Jetty和其他容器如何在坚持Servlet规范的同时利用NIO? [英] How do Jetty and other containers leverage NIO while sticking to the Servlet specification?

查看:183
本文介绍了Jetty和其他容器如何在坚持Servlet规范的同时利用NIO?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是NIO的新手,我正在试图弄清楚Jetty如何利用NIO。

I'm new to NIO, and I am trying to figure out how Jetty leverages NIO.

我对使用阻止IO服务请求的传统servlet容器的理解如下:


  1. 请求到达

  2. 分配一个线程来处理请求和servlet方法( doGet etc)

  3. 将Servlet方法传递给 InputStream OutputStream

  4. servlet方法从 InputStream 读取并写入 OutputStream

  5. InputStream OutputStream 基本上与各自的流相关联底层套接字

  1. A request arrives
  2. A thread is allocated to process the request and the servlet method (doGet etc) is invoked
  3. Servlet method is handed an InputStream and OutputStream
  4. The servlet method reads from the InputStream and writes to the OutputStream
  5. The InputStream and OutputStream are basically tied to the respective streams of the underlying Socket

当NIO连接器是什么时有什么不同用过的?我的猜测如下:


  1. 请求到达

  2. Jetty使用NIO连接器并异步缓冲整个请求

  3. 读取请求后,将缓冲区完全包装在 InputStream
  4. $ b中$ b
  5. 创建一个空响应缓冲区(包含在 OutputStream 中)

  6. 分配一个线程并调用servlet方法( doGet 等)处理上面的包装器流

  7. Servlet方法写入包装(缓冲)响应流并从servlet方法返回

  8. Jetty使用NIO将响应缓冲区内容写入基础 SocketChannel

  1. A request arrives
  2. Jetty uses NIO connector and buffers the entire request asynchronously
  3. Once request has been read completely wrap the buffer in an InputStream
  4. Create an empty response buffer (wrapped in an OutputStream)
  5. Allocate a thread and invoke the servlet method (doGet etc) handing the above wrapper streams
  6. Servlet method writes to the wrapped (buffered) response stream and returns from the servlet method
  7. Jetty uses NIO to write the response buffer contents to the underlying SocketChannel

从Jetty文档中,我发现了以下内容:

SelectChannelConnector - 此连接器使用高效的NIO缓冲区和非阻塞线程模型。 Jetty使用Direct NIO缓冲区,并仅将线程分配给具有请求的连接。同步模拟了对servlet API的阻塞,并且在请求处理结束时任何未刷新的内容都是异步写入的。

SelectChannelConnector - This connector uses efficient NIO buffers with a non-blocking threading model. Jetty uses Direct NIO buffers, and allocates threads only to connections with requests. Synchronization simulates blocking for the servlet API, and any unflushed content at the end of request handling is written asynchronously.

我不确定我理解 同步模拟servlet API的阻塞 意味着什么?

I'm not sure I understand what Synchronization simulates blocking for the servlet API means?

推荐答案

你没有完全正确的。当jetty使用NIO连接器(而9只支持NIO)时,它的工作方式如下:

You don't have it exactly correct. When jetty uses an NIO connector (and 9 only supports NIO) it works as follows:


  1. 空闲状态为几个线程(1-4取决于#core)调用选择器,查找IO活动。这已经扩展到Jetty上超过1,000,000个连接。

  2. 当选择器看到IO活动时,它会在连接上调用句柄方法,该方法可以是:

  1. Idle state as a few threads (1-4 depending on # cores) calling the selector, looking for IO activity. This has been scaled to over 1,000,000 connections on Jetty.
  2. When selector sees IO activity, it calls a handle method on the connection, which either:


  • 其他东西已经注册,它被阻止等待此连接的IO,因此在这种情况下,选择器只会唤醒被阻止的任何人。

  • 否则调度线程来处理连接。

如果调度线程,则会尝试阅读连接并解析它。现在发生的事情取决于连接是http,spdy,http2还是websocket。

If a thread is dispatched, then it will attempt to read the connection and parse it. What happens now depends on if the connection is http, spdy, http2 or websocket.


  • 对于http,如果请求标头完成,则线程继续调用请求的处理(最终这将转到servlet)无需等待任何内容。

  • 对于http2 / spdy,需要另外一次调度,但请参阅列表中关于Eat-What-You-Kill策略的讨论: http://dev.eclipse.org/mhonarc/lists/jetty-dev/msg02166.html

  • for websocket调用消息处理。

将线程分派到servlet后它看起来像servlet IO阻塞,但在HttpInputStream和HttpOutputStream的级别下,所有IO都与回调异步。阻塞API使用特殊的阻塞回调来实现阻塞。这意味着如果servlet选择使用异步IO,那么它只是绕过阻塞回调并且或多或少地直接使用异步API。

Once a thread is dispatched to a servlet, it looks to it like the servlet IO is blocking, but underneath the level of HttpInputStream and HttpOutputStream all the IO is async with callbacks. The blocking API uses a special blocking callback to achieve blocking. This means that if the servlet chooses to use async IO, then it is just bypassing the blocking callback and using the async API more or less directly.

这个视图稍微复杂了http2和spdy,它们是多路复用的,所以它们可能涉及额外的调度。

This view is slightly complicated by http2 and spdy, which are multiplexed, so they can involve an extra dispatch.

任何没有的HTTP框架调度可以在基准代码中真的非常快,但是当面对一个真正的应用程序,可以做一些愚蠢的事情,比如阻塞数据库,文件系统,REST服务等......那么缺乏调度只意味着一个连接可以阻止所有系统上的其他连接。

Any HTTP framework that does not dispatch can go really really fast in benchmark code, but when faced with a real application that can do silly things like block on databases, files system, REST services etc... then lack of dispatch just means that one connection can hold up all the other connections on the system.

有关jetty如何处理异步和调度的更多信息,请参阅:

For some more info on how jetty handles async and dispatch see:

  • https://webtide.com/asynchronous-callbacks/
  • https://webtide.com/jetty-9-goes-fast-with-mechanical-sympathy/
  • https://webtide.com/avoiding-parallel-slowdown-in-jetty-9/
  • https://webtide.com/lies-damned-lies-and-benchmarks-2/
  • https://webtide.com/jetty-in-techempower-benchmarks/

这篇关于Jetty和其他容器如何在坚持Servlet规范的同时利用NIO?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆