Tomcat的BIO连接器和NIO连接器有什么区别?

时间:2012-06-14 12:07:54

标签: tomcat nio

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

从我读到的内容,谈话就像这样

  1. 客户端连接到servlet

  2. Servlet会挂起连接,直到有可用的数据 连接客户端

  3. 数据准备就绪后,服务器会写入httpResponse和 冲了它。这实际上断开了连接?

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

  5. 当这种情况持续发生时会使用多少个线程?

4 个答案:

答案 0 :(得分:53)

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-08-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代替,这是一种更标准的协议。

答案 1 :(得分:5)

NIO使用更少的线程,这意味着使用更少的tcp / ip端口。

你知道端口是1到65534,所以我们可以说NIO可以达到比BIO更高的TPS(每秒事务数)

我测试了协议: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 :(得分:4)

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

答案 3 :(得分:0)

以下是关于NIO连接器的两篇好文章,以防有人考虑BIO之间的差异(请求处理必须接受线程)&在Tomcat中将NIO(请求处理传递到另一个工作线程)。