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

我想知道tomcat NIO连接器的内部。 当我们创build一个实现CometProcessor的servlet时,线程到底有多精确?每个连接仍然是一个线程?

从我所读到的,谈话就是这样的

  1. 客户端连接到一个servlet

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

  3. 数据准备好后,服务器写入httpResponse并刷新它。 这实际上断开连接?

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

当这种情况持续发生时,有多less线程被使用?

NIO和Comet完全无关:你可以混合搭配它们。

使用NIO(或APR)连接器,可以使用线程模型处理更multithreading数较less的请求。 有关连接器之间的比较,请参阅http://tomcat.apache.org/tomcat-7.0-doc/config/http.html#Connector_Comparison

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

您在问题中提出的scheme是典型的阻塞单线程每请求模式。 在步骤4中,Java BIO连接器(通过Tomcat 7默认为up)将继续等待现有连接器上的其他请求 – 用于keepalive HTTP请求。 如果客户端在前一个请求中没有设置Connection:close并且没有closures连接,那么线程将挂起,直到达到存活超时。 如果使用NIO连接器,线程将在发送响应之后立即返回线程池,并且不会在可能永远不会到达的Keepalive请求上“浪费”一个线程。

彗星/ Websocket完全不同的工作方式是将消息传递给一个专门编写的servlet(以及可选的filter),而这些线程仅在需要发送消息或写入数据时才使用。

更新2016-08-19

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

请注意,同样在Tomcat 8.5和9.0中,对Comet的支持已经下降了。 彗星的使用应该全部用更为标准的协议Websocket来代替。

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

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

我testing了两个协议:HTTP/1.1org.apache.coyote.http11.Http11NioProtocol与相同的Web项目,相同的主机和相同的server.xml,但协议。

使用Jmeter进行testing。

我设置了1000个线程来运行请求,在几分钟内HTTP / 1.1,主机使用端口大于30000,TPS只有300!

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

在讨论中join迟了 – 在阻塞IO和asynchronousNIO之间进行性能比较的上下文中,优秀的阅读是“旧的写服务器的方法是新的” 。 总之,下面的线程每个连接模型被发现比NIO版本更好的执行和易于编写 – 与普遍的看法相反。

这里有两个关于NIO连接器的好文章,以帮助有人考虑Tomcat中的BIO(请求处理被绑定为接受线程)和NIO(请求处理被传递到另一个工作者线程)之间的区别。

  • NIO连接器通过Tomcat专家网站
  • Tomcat连接器概述(PDF)