Java OpenResty Spring Spring Boot MySQL Redis MongoDB PostgreSQL Linux Android Nginx 面试 算法 小程序 Arthas JVM juc AQS Docker DevOps


Tomcat acceptCount 和 maxConnections 参数解析

Tomcat Java 大约 3561 字

版本

Tomcat9

参数说明

acceptCount:全连接队列容量,等同于backlog参数,与Linux中的系统参数somaxconn取较小值,Windows中没有系统参数。

maxConnectionsTomcat可以accept的最大容量。acceptSocket编程中的accept方法。

public class ServerSocketDemo {

    public static void main(String[] args) throws Exception {
        ServerSocket server = new ServerSocket(8080, 2); // acceptCount=2

        while (true) {
            server.accept();
        }
    }

}

解析步骤

Spring Boot使用的Embedded Tomcat配置accept-count全连接队列为2max-connections最大可被accept的连接数。

server:
  tomcat:
    accept-count: 2
    max-connections: 3

使用ss -nlt查看全连接队列容量。

[root@fendoudebb ~]# ss -nltp
State         Recv-Q        Send-Q        Local Address:Port        Peer Address:Port        Process                                                      
LISTEN        0             2                         *:8080                   *:*           users:(("java",pid=3475500,fd=18))                       

当连接数超过maxConnection后,新建连接将不再被Tomcat调用accept方法从accept queue全连接队列中获取,从而Recv-Q全连接队列计数变为了1

[root@fendoudebb ~]# ss -nltp
State         Recv-Q        Send-Q        Local Address:Port        Peer Address:Port        Process                                                      
LISTEN        1             2                         *:8080                   *:*           users:(("java",pid=3475500,fd=18))                       

查看当前建立连接的情况,此处的Recv-Q不表示为全连接队列目前长度,而是表示为客户端三次握手成功了但还没被服务端accept获取,连接还停留在全连接队列中,客户端有82个字节发送但还没有被服务端接收。

备注:不是查看监听状态下的连接,Recv-QSend-Q含义不同。-lRecv-Q表示全连接队列目前长度,Send-Q表示全连接队列的容量。没有-lRecv-Q表示客户端有多少个字节发送但还没有被服务端接收,Send-Q就表示为有多少个字节未被客户端接收。

[root@fendoudebb ~]# ss -tnp
State        Recv-Q        Send-Q        Local Address:Port        Peer Address:Port         Process                                                                                                                                       
ESTAB        0             0                     [::1]:8080               [::1]:39624         users:(("java",pid=3475500,fd=25))                                  
ESTAB        0             0                     [::1]:8080               [::1]:39622         users:(("java",pid=3475500,fd=24))                                  
ESTAB        82            0                     [::1]:8080               [::1]:39626                                                                             
ESTAB        0             0                     [::1]:8080               [::1]:39620         users:(("java",pid=3475500,fd=23))   

超出连接后客户端curl一直就停留在SYN-SENT状态,服务端不会再发送SYN+ACK,直到客户端超时断开。

[root@fendoudebb ~]# ss -tnp
State           Recv-Q        Send-Q        Local Address:Port         Peer Address:Port        Process     
SYN-SENT        0             1                 127.0.0.1:41734           127.0.0.1:8080         users:(("curl",pid=3476127,fd=3))   

客户端请求超时(需要等待一定时间)。

[root@fendoudebb ~]# curl -vv http://127.0.0.1:8080/test
*   Trying 127.0.0.1...
* TCP_NODELAY set
* connect to 127.0.0.1 port 8080 failed: Connection timed out
* Failed to connect to 127.0.0.1 port 8080: Connection timed out
* Closing connection 0
curl: (7) Failed to connect to 127.0.0.1 port 8080: Connection timed out

相关代码

org.apache.tomcat.util.net.AbstractEndpoint

/**
 * Allows the server developer to specify the acceptCount (backlog) that
 * should be used for server sockets. By default, this value
 * is 100.
 */
private int acceptCount = 100;
public void setAcceptCount(int acceptCount) { if (acceptCount > 0) this.acceptCount = acceptCount; }
public int getAcceptCount() { return acceptCount; }

参考

https://tomcat.apache.org/tomcat-9.0-doc/config/http.html

阅读 157 · 发布于 2022-04-13

————        END        ————

Give me a Star, Thanks:)

https://github.com/fendoudebb

扫描下方二维码关注公众号和小程序↓↓↓

扫描二维码关注我
昵称:
随便看看 换一批