Tomcat和acceptCount无法正常工作

时间:2018-04-28 17:56:07

标签: tomcat spring-boot tomcat8

我使用tomcat 8作为Spring Boot项目的一部分,我的acceptCount设置似乎无法正常工作。我的服务器不仅接受了300个连接,而且还接受了几乎1000个连接,但当然它同时处理的连接数不超过200个。

在acceptCount上似乎清楚了Tomcat文档:"当所有可能的请求处理线程都在使用时,传入连接请求的最大队列长度。队列已满时收到的任何请求都将被拒绝。"但显然这不会发生。

当然还有另一个设置,maxConnections及其文档说:"请注意,一旦达到限制,操作系统仍然可以接受基于acceptCount设置的连接" - 但这个说明并不意味着acceptCount是"指望在maxConnections之上,而不是maxThreads" (就像https://coderanch.com/t/647733/application-servers/Tomcat-BIO-connector-configurations认为的主题启动者一样)。它只是意味着它将在两种情况下产生影响:当所有处理线程都忙,并且所有可用连接都耗尽时。 (即使那个人是正确的,这也意味着Tomcat文档在定义acceptCount时是完全错误的......)

那为什么会被忽略?我发现有人提到讨论人们据称声称acceptCount不适用于他们,但没有找到实际的讨论:(即使相反,我也能找到一些关于Tomcat如何在300连接后窒息的抱怨(这完全是默认的) maxThreads + acceptCount)。所以我可以看到,对于某些人来说,它有效,而且我被要求相信"可能"对于某些人它没有。也不适合我。我是否应该相信Tomcat手册从某种意义上说这个选项并不总是受到尊重是错误的吗?

2 个答案:

答案 0 :(得分:2)

所有这些设置之间存在复杂的关系,并且您选择的连接器(例如BIO,NIO,APR等)使它们变得更加复杂。

BIO连接器基本上已经死了......它在Tomcat 8.0.x之后不存在。它不能接受比线程池一次可以处理的更多连接。因此,BIO连接器实际上是maxConnections == maxThreads。因此,对于BIO连接器,服务器愿意接受的连接数应为maxConnections + acceptCount,但maxConnections仅限于相对较小的数量。

其他更复杂的连接器允许每个线程有多个连接在TCP / IP意义上接受maxConnections的默认值接近10k(不同)通过精确类型),并且线程池大小不相关,因此服务器愿意接受的连接数为maxConnections + acceptCount

非BIO连接器可以接受更多连接的原因是因为两个状态不需要活动请求处理线程(等待下一个HTTP-keepalive-request - 使用read()并等待对于下一个连接 - 使用accept())由一个单独的线程完成,允许请求处理线程尽快返回池中,以便为其他请求提供服务。

如果您正在使用BIO,我希望连接失败后,例如300个连接(你没有发布你的配置,所以不可能说实际的数字是什么)但是对于NIO,我预计它会在10k连接以北。

对于测试,重要的是您实际上没有对您的连接做任何事情以便正确计算它们。基本上,您需要这样做:

foreach(i from 0..10301)
    conn[i] = connect('host:port')

您应该发现有一些i服务器不接受连接。如果您连接并发出GET /,则服务器将响应,连接请求处理线程将返回其各自的池中。

**阅读一些评论后更新**

我希望能够同时处理200个请求,但Tomcat会很乐意在内部排队另外800个请求。 acceptQueue中的附加200正在由操作系统的TCP / IP堆栈排队,而不是由Tomcat / Java排队

假设客户端有无限的读取超时,我希望你能够启动1201个curl个实例,其中门前的200个实例立即得到一个线程(并且睡眠),下一个800在Tomcat / Java中排队,接下来的200个在TCP / IP堆栈中排队,而实例#1201得到一个"连接被拒绝"响应。

完成第一组200个请求后,Tomcat将处理另一批200个请求,TCP / IP队列中的200个连接将从该队列移动到Tomcat / Java队列,20秒后第二个集合200个请求将完成。这将重复,直到所有1200个初始请求返回对其客户的响应。 1200个请求中只有1个将被拒绝。

答案 1 :(得分:0)

NIO的

acceptCount作为第二个参数(backlog)传入ServerSocket.bind(SocketAddress,int)。该方法的Javadoc说:

  

backlog参数是请求的最大数量   套接字上的挂起连接。它的确切语义是实现   具体。特别地,实现可以施加最大长度   或者可以选择完全忽略参数。

看起来它在JVM中被忽略了。