Tomcat 和 acceptCount 不工作

Tomcat and acceptCount not working

我正在使用 tomcat 8 作为 Spring 引导项目的一部分,我的 acceptCount 设置似乎不起作用。我的服务器接受了将近 1000 个连接,而不是只接受 300 个连接,当然同时处理的连接不超过 200 个。

Tomcat 文档似乎对 acceptCount 很清楚:"The maximum queue length for incoming connection requests when all possible request processing threads are in use. Any requests received when the queue is full will be refused." 但显然这不会发生。

当然还有另一个设置,maxConnections,它的文档说:"Note that once the limit has been reached, the operating system may still accept connections based on the acceptCount setting" - 但单独的注释并不意味着 acceptCount 是 "count on top of maxConnections, not maxThreads"(就像 https://coderanch.com/t/647733/application-servers/Tomcat-BIO-connector-configurations 的 topicstarter认为)。这只是意味着它在两种情况下都会产生影响:当所有处理线程都忙时,以及当所有可用连接都耗尽时。 (即使那个人是正确的,那也意味着 Tomcat 文档在定义 acceptCount 时是完全错误的...)

那为什么会被忽略呢?我发现一些讨论提到人们声称 acceptCount 对他们不起作用,但没有找到实际的讨论 :( 即使相反,我也能找到一些关于 Tomcat 在 300 个连接后如何阻塞的抱怨(这正是默认的 maxThreads + acceptCount)。所以我可以看到它对某些人有效,并且我被要求相信 "maybe" 对于某些人它没有。也不适合我。我应该相信 "maybe" =26=] 手册是错误的,因为这个选项并不总是被尊重?

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

BIO 连接器基本上已失效...它在 Tomcat 8.0.x 之后不存在。它不能接受超过线程池一次可以处理的连接数。因此,BIO connector本质上是maxConnections == maxThreads。因此,对于一个BIO连接器来说,服务器愿意接受的连接数应该是maxConnections + acceptCount,但是maxConnections被限制在一些比较小的数目。

其他连接器更复杂,在 TCP/IP sense.The 默认值中允许每个线程接受多个连接 maxConnections 接近 10k(因具体类型而异),与线程池大小无关,因此服务器愿意接受的连接数为 maxConnections + acceptCount.

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

如果您使用的是 BIO,我预计连接会在例如300 个连接(您没有 post 您的配置,因此无法说出实际数字是多少)但对于 NIO,我希望它超过 10k 个连接。

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

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

您应该会发现服务器不接受某些 i 的连接。如果您连接并发出 GET / 然后服务器将响应并且连接 请求处理线程将返回到它们各自的池中。

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

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

假设客户端无限读取超时,我希望您能够启动 curl 的 1201 个实例,其中门中的前 200 个立即获得一个线程(并休眠),下一个800 个在 Tomcat/Java 中排队,接下来的 200 个在 TCP/IP 堆栈中排队,实例 #1201 获得 "connection refused" 响应。

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

NIO 的

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

The backlog argument is the requested maximum number of pending connections on the socket. Its exact semantics are implementation specific. In particular, an implementation may impose a maximum length or may choose to ignore the parameter altogether.

您的 JVM 似乎忽略了它。