Tomcat的BIO Connector和NIO Connector有啥区别?

Posted

技术标签:

【中文标题】Tomcat的BIO Connector和NIO Connector有啥区别?【英文标题】:What is the difference between Tomcat's BIO Connector and NIO Connector?Tomcat的BIO Connector和NIO Connector有什么区别? 【发布时间】:2012-06-17 11:09:37 【问题描述】:

我想知道tomcat NIO 连接器的内部结构。当我们创建一个实现 CometProcessor 的 servlet 时,线程究竟是如何使用的?每个连接仍然是一个线程吗?

根据我的阅读,对话是这样的

    客户端连接到 servlet

    Servlet 一直挂在连接上,直到有任何可用数据 到连接的客户端

    当数据准备好时,服务器写入 httpResponse 和 冲洗它。这实际上断开了连接?

    客户端发送另一个请求,服务器再次挂起..

这种情况持续发生时使用了多少线程?

【问题讨论】:

你指的是哪个版本的Tomcat?这种行为在 Tomcat 7 的更高版本和 Tomcat 8 中正在发生变化。 【参考方案1】:

NIO 和 Comet 完全不相关:您可以混合搭配。

由于线程模型,使用 NIO(或 APR)连接器允许您用更少的线程处理更多请求。有关连接器之间的比较,请参阅 http://tomcat.apache.org/tomcat-7.0-doc/config/http.html#Connector_Comparison。

Comet(和 Websocket)具有完全不同的调度模型,它需要不同的应用架构并以不同的方式实现更高的吞吐量。

您在问题中提出的场景是典型的阻塞每个请求一个线程的模型。在第 4 步中,Java BIO 连接器(它是 Tomcat 7 之前的默认连接器)将继续等待现有连接器上的其他请求——对于 keepalive HTTP 请求。如果客户端在之前的请求上没有设置Connection:close,也没有关闭连接,线程会挂起,直到达到keepalive超时。如果您使用 NIO 连接器,则线程将在响应发送后立即返回线程池,您不会“浪费”线程处理可能永远不会到达的 keepalive 请求。

Comet/Websocket 的工作方式完全不同,它将消息传递给专门编写的 servlet(和可选过滤器),并且线程仅在有消息要发送或数据要写入时使用。

2016 年 8 月 19 日更新

Tomcat 8.5 和 9.0 完全放弃了 BIO 连接器。这是因为许多新的 API 和技术(例如 Websocket)需要非阻塞语义,并且在阻塞 API 之上构建非阻塞服务非常非常困难。完成这项工作所需的代码使 Tomcat 代码的其余部分变得非常难看,等等,因此决定完全放弃 BIO 连接器。因此对于 Tomcat 8.5 及更高版本,只有 NIO、NIO2 和基于 APR 的连接器可用。

请注意,同样在 Tomcat 8.5 和 9.0 中,对 Comet 的支持已被删除。 Comet 的使用都应该被 Websocket 取代,这是一个更标准的协议。

【讨论】:

听起来NIO是双赢的,那为什么APR不可用的时候默认BIO呢? @Jayen BIO 是 Tomcat 到 7.0.x 的默认连接器。在 Tomcat 8 中,NIO 是default connector。 有什么原因它不是 tomcat 6 或 7(使用 java 7)的默认设置? @Jayen 是的,它在 Tomcat 6 中仍处于试验阶段,并且在 Tomcat 7 发布后决定将 NIO 设为默认值。因此,与其在单点版本中更改默认连接器并可能导致各种问题,不如在 Tomcat 8 中切换到 NIO-default。任何人都可以随意显式地将其连接器更改为 NIO……这只是默认设置情况发生了变化,此时 NIO 连接器相当稳定。 我有一个关于“如果您使用 NIO 连接器,线程将在发送响应后立即返回线程池的问题,并且您不会在 keepalive 请求上“浪费”线程可能永远都不会到达。”,听起来在蔚来,keepalive是没有意义的?【参考方案2】:

这里有两篇关于 NIO 连接器的好文章,以帮助人们考虑 Tomcat 中 BIO(请求处理必然接受线程)和 NIO(请求处理被传递到另一个工作线程)之间的差异。

NIO Connector via Tomcat Expert site Overview of Tomcat connectors (PDF)

【讨论】:

tomcat-expert 文章指的是 NIO AJP 连接器,而不是 http 连接器【参考方案3】:

添加到这个讨论的后期 - 在阻塞 IO 和异步 NIO 之间的性能比较的上下文中 - 一个很好的阅读是 "Old way of writing servers is new"。总之,与以下相比,每个连接模型的线程被发现性能更好且易于编写 NIO 版本 - 与流行的看法相反。

【讨论】:

【参考方案4】:

NIO 使用较少的线程,表示使用的 tcp/ip 端口较少。

你知道端口是1到65534,所以我们可以说NIO可以达到比BIO更高的TPS(Transactions Per Second)

我测试了协议:HTTP/1.1org.apache.coyote.http11.Http11NioProtocol 具有相同的 Web 项目、相同的主机和相同的 server.xml,但协议相同。

使用 jmeter 进行测试。

我设置了1000个线程来运行请求,几分钟后HTTP/1.1时,主机使用的端口超过30000,TPS只有300!

当org.apache.coyote.http11.Http11NioProtocol时,使用端口的最大计数永远不会超过3000,tps超过1200!

【讨论】:

请重新阅读您的帖子,很难理解。我做了一些编辑以帮助清除它。如果你想开始一个新段落,你需要 2 个回车。 每秒事务数 TPS 测量高度依赖于使用情况。 NIO 还需要比 BIO 更多的资源(特别是 CPU)。决定使用哪个连接器的最佳方法是对您自己的应用程序进行基准测试,看看它在不同条件和配置下的性能。 还要注意端口使用是无关紧要的,这里:每个连接器,无论是什么类型(BIO、NIO、NIO2、APR)都使用一个 TCP/IP 端口。 您的基准测试是否可重现,您介意分享一下吗?我假设您在 Jmeter 客户端上启用了 keep-alive,并且没有在 servlet 中做太多 CPU 工作,从而为 NIO 提供了更好的 TPS。

以上是关于Tomcat的BIO Connector和NIO Connector有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat Connector三种运行模式(BIO, NIO, APR)的比较和优化

tomcat connector : bio nio apr

Tomcat Connector三种执行模式(BIO, NIO, APR)的比較和优化

Tomcat 的三种(bio,nio.apr) 高级 Connector 运行模式

Tomcat Connector(BIO, NIO, APR)三种运行模式(转)

tomcat架构分析 (connector NIO 实现)