Tomcat 连接器架构、线程池和异步 servlet
Posted
技术标签:
【中文标题】Tomcat 连接器架构、线程池和异步 servlet【英文标题】:Tomcat connector architecture, thread pools and async servlets 【发布时间】:2014-10-10 23:26:33 【问题描述】:我想了解 Tomcat 的 BIO 和 NIO 连接器线程模型。我正在参考连接器的官方 Tomcat 7 文档,可以在 here 找到。基于它,这是我所怀疑的:
acceptorThread(s) :这是一个或最多 2 个线程(如文档中所述),仅负责接受传入的连接。这可以使用acceptorThreadCount进行配置,建议多cpu机器可以使用两个以上—— 这是为什么? 这是否意味着同时打开的连接数随着 cpu 的数量与服务器系统上允许的打开文件描述符的数量成比例? 最大连接数: 此设置与acceptCount 和系统上打开的文件描述符的数量有什么关系。 为什么 NIO 连接器 (10000) 的默认值比 BIO (= maxThreads) 高这么多? acceptCount :这是所有请求处理线程都忙时的请求队列。 当请求被放入此队列时,是否也为其分配了文件描述符?还是只有在主动处理请求时才使用文件描述符? 请求处理线程 :该池中的线程数由 maxThreads 和 minSpareThreads 属性配置。 这个线程池和 acceptorThreads 有什么关系?接受者线程是否在这个池中产生线程? 据我了解,NIO 模型在请求处理线程方面比 BIO 模型更有效。它是如何实现这种效率的? 正如我在各种资料中看到的那样,NIO 模型中的线程遵循每个请求线程 范式与 BIO 模型的每个连接线程 范式。此外,在 NIO 连接器模型中,实际请求处理被委托给不同的、应用程序监控的线程,而服务器的请求处理线程则免费返回到线程池以接受更多连接。 那么,这是否意味着 NIO 模型的好处只有在与服务器的连接具有 HTTP Keep-Alive 特性或应用程序使用 Servlet 时才会显现出来3.0的异步处理特性? Servlet 3.0: 使用 Servlet 3.0 时,应用程序 servlet 线程池的大小(相对于连接器线程池的大小)应该是多少才能达到最佳效率? 当同时使用 BIO 模型和此模型时,处理请求的方式会有什么不同(假设连接器线程仍将使用 每个连接线程 模型)?请注意:所有关于 tomcat 7 的讨论。
【问题讨论】:
【参考方案1】:acceptorThread(s) :这是一个或最多 2 个线程(如 文档中提到的),它只负责接受 传入连接。这可以使用 acceptorThreadCount,建议多用两个 对于多 CPU 机器 -
这是为什么?
接受连接是一项成本非常低的操作,因此将多个线程专用于该任务是没有意义的。
Does this imply that the number of simultaneous open connections scales with the number of cpus versus the number of open file descriptors allowed on the server system ?
不,不是因为它在 CPU 方面的成本非常低。至于文件描述符,每个接受的连接都将使用一个文件描述符,因此服务器可以接受的最大连接数受可用文件描述符的数量限制。
最大连接数:
这个设置和acceptCount和数量有什么关系 系统上打开的文件描述符。
maxConnections 不能大于系统上打开的文件描述符的数量。请记住,其他进程也使用文件描述符,因此对于可用的文件描述符,可能希望对 maxConnections 保持保守,比如说 maxConnections
Why is the default value for this so much higher for the NIO connector ( 10000 ) than for the BIO ( = maxThreads ) ?
这是因为在 NIO 中单个处理所有 IO,而在 BIO 中,服务器需要为每个连接创建/使用单独的线程。
acceptCount :这是所有请求处理线程都忙时的请求队列。
当请求被放入这个队列时,是否也分配了一个文件描述符?
是的,这是正确的,连接请求已被接受,但服务器尚未准备好为请求提供服务,因此连接被放置在队列中。这样做是为了防止 TCP/堆栈超时连接请求,从客户端的角度来看,连接请求可能看起来像服务器停机。换句话说,服务器说“我在这里,一旦我有资源可以处理您的请求”。
还是只有在主动处理请求时才消耗文件描述符?
没有。
希望这会有所帮助。
问候,
斯拉瓦·伊梅舍夫
【讨论】:
非常感谢您的回答。你能再推测一个问题吗?要构建一个真正可扩展的服务器(根据当前要求同时处理大约 10000 个请求),NIO 是唯一的出路吗?我问这个是因为,根据许多文献,BIO 连接器是更稳定的连接器(尽管我不太确定这里的“稳定”意味着什么)。或者我应该完全放弃 TC 并查看其他基于事件的替代方案,例如 jetty 或 jboss? 我会说是的,NIO 是要走的路。问题是,您将能够处理连接数,您的应用程序并行处理这些请求的能力可能是另一回事。你最终可能需要运行多台服务器,所以你必须从一开始就考虑历史可扩展性,并相应地设计系统。顺便说一句,Tomcat 有 NIO 连接器:tomcat.apache.org/tomcat-7.0-doc/config/…以上是关于Tomcat 连接器架构、线程池和异步 servlet的主要内容,如果未能解决你的问题,请参考以下文章