You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Boot 2.5.8嵌入式Tomcat无法从同一源IP建立多端口并发连接的问题排查与解决

嵌入式Tomcat(Spring Boot 2.5.8)多TCP连接建立失败的排查与解决

这种单连接正常、多并发连接卡壳的情况,我在处理Spring Boot嵌入式Tomcat问题时碰到过好几次,结合你的Wireshark抓包信息,咱们可以从这几个方向逐一排查:

1. Tomcat核心连接参数配置受限

Spring Boot 2.5.8默认用NIO模式的Tomcat,虽然默认的maxConnections(最大同时连接数)是10000,acceptCount(连接等待队列大小)是100,但如果你的应用曾修改过这些参数,或者某些自定义配置覆盖了默认值,就可能导致新连接被拒绝。比如如果不小心把maxConnections设成1,那自然只能处理一个连接。

解决方法
application.propertiesapplication.yml里明确配置这两个参数:

# 最大同时连接数,根据服务器性能调整
server.tomcat.max-connections=20000
# 连接等待队列大小,建议和操作系统的somaxconn参数一致
server.tomcat.accept-count=1000

2. 操作系统层面的TCP连接限制

即使Tomcat配置没问题,操作系统的TCP栈参数也可能拖后腿。比如Linux下的net.ipv4.tcp_max_syn_backlog(SYN半连接队列大小)和net.core.somaxconn(全连接队列大小)如果设置过小,当并发连接请求过来时,服务器会直接丢弃超出队列的SYN包,这就会出现你看到的第二个连接无法建立的情况。

解决方法

  • 查看当前参数值:
    sysctl net.ipv4.tcp_max_syn_backlog
    sysctl net.core.somaxconn
    
  • 修改参数(临时生效,重启后会恢复):
    sysctl -w net.ipv4.tcp_max_syn_backlog=4096
    sysctl -w net.core.somaxconn=1000
    
  • 要永久生效,把这两行添加到/etc/sysctl.conf文件,然后执行sysctl -p加载配置。

另外,还要检查服务器防火墙(比如iptables、firewalld)有没有针对8081端口设置并发连接限制,有的话需要调整规则。

3. Tomcat线程池耗尽导致无法处理新连接

如果你的应用请求处理逻辑耗时很长(比如调用外部接口超时、数据库查询慢),Tomcat的线程池(默认maxThreads=200)可能会被占满。虽然TCP连接可能已经完成握手,但因为没有可用线程处理请求,客户端会感觉连接“没建立”——你可以再确认下Wireshark抓包的握手阶段状态是否完成。

解决方法

  • 调整线程池参数:
    server.tomcat.max-threads=500
    server.tomcat.min-spare-threads=100
    server.tomcat.max-queue-capacity=1000
    
  • 排查应用的慢请求,比如用Spring Boot Actuator的/actuator/threaddump接口查看阻塞线程,优化耗时的业务逻辑。

4. 自定义Tomcat配置出错

如果你的代码里自定义了TomcatServletWebServerFactory来配置Connector,一定要检查有没有误设连接限制参数。比如不小心把setMaxConnections(1)或者setAcceptCount(0)写进去,那肯定只能处理一个连接。

检查方法
查看你的配置类,比如:

@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    factory.addConnectorCustomizers(connector -> {
        // 这里要确认没有错误的连接限制配置
        connector.setPort(8081);
        // 确保用的是NIO模式,BIO模式的并发能力弱很多
        connector.setProtocol("org.apache.coyote.http11.Http11NioProtocol");
    });
    return factory;
}

5. 网络或客户端侧限制

最后,再确认下网络链路和客户端的问题:

  • 在服务器端用tcpdump抓8081端口的包,看是否收到第二个连接的SYN包。如果没收到,说明是客户端没发出来,或者中间网络设备(路由器、防火墙)拦截了;如果收到了但服务器没回复ACK,那还是回到服务器端的配置问题。
  • 检查客户端操作系统的并发连接限制,比如Windows下的TCP连接数限制,或者客户端程序本身的连接池配置错误。

排查步骤总结

  1. tcpdump在服务器端确认是否收到第二个连接的SYN包;
  2. 检查Tomcat的maxConnectionsacceptCount和线程池参数;
  3. 调整操作系统的TCP栈参数;
  4. 排查自定义Tomcat配置和应用慢请求;
  5. 验证网络链路和客户端限制。

内容的提问来源于stack exchange,提问作者Igor_M

火山引擎 最新活动