Jetty 和其他容器如何在遵守 Servlet 规范的同时利用 NIO?

2024-03-31

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

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

  1. 请求到达
  2. 分配一个线程来处理请求和 servlet 方法(doGet等)被调用
  3. Servlet 方法被传递给InputStream and OutputStream
  4. Servlet 方法读取InputStream并写信给OutputStream
  5. The InputStream and OutputStream基本上与底层的各自流相关Socket

使用NIO连接器有什么不同?我的猜测是这样的:

  1. 请求到达
  2. Jetty 使用 NIO 连接器并异步缓冲整个请求
  3. 一旦请求被完全读取,将缓冲区包装在一个InputStream
  4. 创建一个空的响应缓冲区(包裹在OutputStream)
  5. 分配一个线程并调用 servlet 方法(doGet等)处理上述包装流
  6. Servlet 方法写入包装(缓冲)的响应流并从 Servlet 方法返回
  7. Jetty使用NIO将响应缓冲区内容写入底层SocketChannel

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

选择通道连接器 http://wiki.eclipse.org/Jetty/Howto/Configure_Connectors#SelectChannelConnector- 该连接器使用高效的 NIO 缓冲区和非阻塞线程模型。 Jetty 使用 Direct NIO 缓冲区,并且仅将线程分配给有请求的连接。同步模拟 servlet API 的阻塞,并且请求处理结束时任何未刷新的内容都是异步写入的。

我不确定我明白什么Synchronization simulates blocking for the servlet API means?


你没有完全正确。当jetty使用NIO连接器(并且9仅支持NIO)时,它的工作原理如下:

  1. 空闲状态为几个线程(1-4,取决于 # 个核心)调用选择器,寻找 IO 活动。 Jetty 上的连接数已超过 1,000,000 个。
  2. 当选择器看到 IO 活动时,它会调用连接上的句柄方法,该方法可以:

    • 其他东西已经注册,它在等待此连接的 IO 时被阻塞,因此在这种情况下,选择器只会唤醒被阻塞的人。
    • 否则将分派一个线程来处理连接。
  3. 如果调度一个线程,那么它将尝试读取连接并解析它。现在发生的情况取决于连接是 http、spdy、http2 还是 websocket。

    • 对于 http,如果请求标头完整,线程将继续调用请求的处理(最终到达 servlet),而不等待任何内容。
    • 对于 http2/spdy 需要另一次调度,但请参阅列表中有关 Eat-What-You-Kill 策略的讨论:http://dev.eclipse.org/mhonarc/lists/jetty-dev/msg02166.html http://dev.eclipse.org/mhonarc/lists/jetty-dev/msg02166.html
    • 对于 websocket,调用消息处理。
  4. 一旦线程被分派到 servlet,看起来 servlet IO 正在阻塞,但在 HttpInputStream 和 HttpOutputStream 级别之下,所有 IO 都与回调异步。阻塞API使用特殊的阻塞回调来实现阻塞。这意味着如果 servlet 选择使用异步 IO,那么它只是绕过阻塞回调并或多或少地直接使用异步 API。

  5. Servlet 可以使用 request.startAsync 挂起,在这种情况下,分派的线程将返回到线程池,但关联的连接不会标记为对 IO 感兴趣。可以执行异步 IO,但是一旦异步周期完成,就需要 AsyncContext 事件来重新分配线程或重新注册 IO 活动的连接。

这个视图由于http2和spdy而稍微复杂一些,它们是复用的,因此它们可能涉及额外的调度。

任何不分派的 HTTP 框架都可以在基准代码中运行得非常快,但是当面对一个真正的应用程序时,它可以做一些愚蠢的事情,比如阻塞数据库、文件系统、REST 服务等……那么缺乏分派就意味着一个连接可以保留系统上的所有其他连接。

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

  • https://webtide.com/asynchronous-callbacks/ https://webtide.com/asynchronous-callbacks/
  • https://webtide.com/jetty-9-goes-fast-with-mechanical-sympathy/ https://webtide.com/jetty-9-goes-fast-with-mechanical-sympathy/
  • https://webtide.com/avoiding-parallel-slowdown-in-jetty-9/ https://webtide.com/avoiding-parallel-slowdown-in-jetty-9/
  • https://webtide.com/lies-damned-lies-and-benchmarks-2/ https://webtide.com/lies-damned-lies-and-benchmarks-2/
  • https://webtide.com/jetty-in-techempower-benchmarks/ https://webtide.com/jetty-in-techempower-benchmarks/
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Jetty 和其他容器如何在遵守 Servlet 规范的同时利用 NIO? 的相关文章

随机推荐