Tomcat连接器架构、线程池和异步Servlets

29
我想了解Tomcat BIO 和 NIO 连接器的线程模型。我参考了官方 Tomcat 7 连接器文档,可以在此处找到。根据文档,这是我所怀疑的:
- acceptorThread(s):这是一个或最多两个线程(如文档中所述),仅负责接受进入的连接。可以使用acceptorThreadCount进行配置,建议在多CPU机器上使用两个以上 - - 为什么要这样做? - 这是否意味着同时打开的连接数会随着CPU数量而缩放,而不是与服务器系统允许的打开文件描述符数有关?
- maxConnections(s): - 此设置与acceptCount和系统上打开的文件描述符数量之间有何关系。 - 为什么NIO连接器的默认值(10000)比BIO连接器高得多(= maxThreads)?
- acceptCount:当所有请求处理线程都忙时,这是请求队列。 - 当将请求放入此队列时,是否也为其分配文件描述符?或者只有在主动处理请求时,才会消耗文件描述符?
- request processing threads:此池中的线程数由maxThreads和minSpareThreads属性配置。 - 此线程池与acceptorThreads之间的关系是什么?接受线程是否会生成此池中的线程? - 据我了解,NIO模型比BIO模型在请求处理线程方面更高效。它如何实现这种效率?
  • 根据多个来源的阅读,NIO模型中的线程遵循“每个请求一个线程”的范例,而BIO模型中则是“每个连接一个线程”的范例。此外,在NIO连接器模型中,实际的请求处理被委托给不同的应用程序监控线程,而服务器的请求处理线程则返回到线程池中,可以自由地接受更多的连接。 因此,这是否意味着只有当连接到服务器的方式是HTTP Keep-Alive或应用程序使用Servlet 3.0的异步处理功能时,NIO模型的优势才会显现?
  • Servlet 3.0
    • 在使用Servlet 3.0时,为了实现最佳效率,应用程序Servlet线程池的大小(相对于连接器线程池大小)应该是多少?
    • 当使用BIO模型时,这两者一起使用时,请求处理的方式是否会有所不同(考虑到连接器线程仍然使用“每个连接一个线程”的模式)?
  • 请注意:所有讨论均与tomcat 7相关。

    1个回答

    15
    • acceptorThread(s):这是一个或最多两个线程(如文档中所述),其仅负责接受传入的连接。可以使用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成本非常低。至于文件描述符,每个已接受的连接都将使用一个文件描述符,因此服务器能够接受的最大连接数受可用文件描述符数量的限制。

    • maxConnections(s)
    • 这个设置与acceptCount和系统中打开的文件描述符数量有什么关系?

    maxConnections不能超过系统中打开的文件描述符数量。请记住,其他进程也使用文件描述符,因此在考虑可用文件描述符时可能需要对maxConnections保持保守,例如 maxConnections < 文件描述符 / 2。

    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 /堆栈超时连接请求,从客户端的角度看,这可能看起来像是服务器已经关闭了。换句话说,服务器说:“我在这里,一旦有资源处理你的请求,我就会处理它。”
    请求是否正在被处理,才会消耗文件描述符吗?
    没有。
    希望这有所帮助。
    谢谢,
    Slava Imeshev

    1
    非常感谢您的回答。您能否再推测一个问题呢?为了构建一个真正可扩展的服务器(根据当前要求处理约10000个并发请求),NIO是唯一的选择吗?我之所以问这个问题,是因为根据许多文献,BIO连接器更加稳定(尽管我不太确定“稳定”在这里意味着什么)。或者,我应该完全放弃TC,转向其他基于事件的替代方案,例如jetty或jboss? - mahasamatman
    1
    我会说是的,NIO 是正确的选择。问题在于,你将能够处理连接数,但你的应用程序处理这些请求的并行能力可能是另一回事。最终你可能需要运行多个服务器,因此你必须从一开始就考虑历史可扩展性,并相应地设计系统。顺便说一下,Tomcat 有 NIO 连接器:https://tomcat.apache.org/tomcat-7.0-doc/config/http.html#NIO_specific_configuration - Slava Imeshev

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接