在使用 JMeter 进行压力测试时,遇到 java.net.ConnectException: Connection refused: connect 异常是很常见的,这通常意味着 JMeter 无法与目标服务器建立连接。今天就来深度剖析一下这个问题,并分享我的排查和优化经验。
问题场景重现与分析
假设我们正在使用 JMeter 对一个基于 Spring Boot 构建的 Web 应用进行压力测试。这个应用部署在 Nginx 反向代理服务器之后,使用了多个Tomcat实例做负载均衡。在 JMeter 中设置了 100 个线程,循环 100 次请求某个接口。运行一段时间后,JMeter 开始抛出 java.net.ConnectException: Connection refused: connect 异常。
这个异常表明客户端(JMeter)尝试连接服务器时,服务器拒绝了连接请求。 可能的原因有很多,我们需要逐一排查:
- 服务器未启动或端口未监听:确认目标服务器是否正常运行,监听的端口是否正确。使用
netstat -an | grep <端口号>命令可以查看端口监听情况。 - 防火墙阻止连接:服务器防火墙可能阻止了来自 JMeter 客户端的连接。检查防火墙规则,确保允许 JMeter 的 IP 地址访问目标端口。
- 服务器资源耗尽:服务器可能由于 CPU、内存或文件描述符等资源耗尽,无法处理新的连接请求。使用
top、free -m、ulimit -n等命令可以监控服务器资源使用情况。 - 网络问题:JMeter 客户端和服务器之间的网络可能存在问题,例如路由故障、网络拥塞等。使用
ping、traceroute等命令可以测试网络连通性。 - Nginx 配置错误:Nginx 配置不当可能导致连接被拒绝。例如,upstream 服务器列表配置错误、反向代理配置错误等。
- 后端Tomcat服务器过载:如果后端 Tomcat 服务器承受不了大量的并发请求,也可能导致连接被拒绝。检查Tomcat的配置,如
maxThreads,acceptCount等。
底层原理深度剖析
java.net.ConnectException 属于 Java 的网络编程异常,它发生在 TCP 连接建立的三次握手阶段。当客户端发起 SYN 包到服务器时,如果服务器因为某些原因(例如端口未监听、资源耗尽)无法响应 SYN+ACK 包,客户端就会收到 RST 包,从而抛出 Connection refused 异常。
在压力测试场景中,如果 JMeter 产生的并发连接数超过了服务器能够承受的范围,就会出现大量的连接被拒绝的情况。这可能是因为服务器的 TCP 连接队列已满,或者服务器的资源已经耗尽。
Nginx 作为反向代理服务器,可以有效地保护后端服务器,防止其直接暴露在公网上。但是,如果 Nginx 本身配置不当,或者 Nginx 无法及时将请求转发到后端服务器,也会导致连接被拒绝。
代码/配置解决方案
下面是一些常见的解决方案,以及相应的代码或配置示例:
- 检查服务器端口监听
netstat -an | grep 8080 # 检查 8080 端口是否被监听
- 关闭或配置防火墙
# 临时关闭防火墙(不推荐在生产环境中使用)
systemctl stop firewalld
# 允许 JMeter 客户端的 IP 地址访问 8080 端口
firewall-cmd --permanent --add-port=8080/tcp --add-source=<JMeter 客户端 IP>
firewall-cmd --reload
- 优化服务器资源
增加服务器的 CPU、内存等资源。
调整 Linux 内核参数,例如
tcp_syn_retries、tcp_synack_retries等。增加文件描述符限制:

# 修改 /etc/security/limits.conf 文件 * soft nofile 65535 * hard nofile 65535 # 重新登录或重启服务器使配置生效
- 优化 Nginx 配置
增加 Nginx 的 worker 进程数:
worker_processes auto;调整 Nginx 的连接数限制:
events { worker_connections 10240; }优化 Nginx 的 upstream 配置:

upstream backend { server backend1.example.com weight=5; server backend2.example.com weight=5; # 增加连接超时时间 keepalive 32; # 保持长连接,减少握手开销 }
- 优化 Tomcat 配置
修改 Tomcat 的 server.xml 文件,增加 maxThreads 和 acceptCount 的值:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="400" <!-- 最大线程数,根据服务器性能调整 -->
acceptCount="200" <!-- 允许等待的最大连接数 -->
/>
- JMeter 调优
- 使用非 GUI 模式运行 JMeter:
jmeter -n -t test.jmx -l result.jtl - 减少 JMeter 的线程数和循环次数,逐步增加压力。
- 使用分布式测试,将压力分散到多个 JMeter 节点上。
实战避坑经验总结
- 监控是关键:在进行压力测试之前,一定要配置好服务器的监控系统,例如 Prometheus + Grafana、Zabbix 等。通过监控系统,可以实时了解服务器的资源使用情况,及时发现问题。
- 逐步增加压力:不要一开始就使用过高的并发数,应该逐步增加压力,观察服务器的响应情况。如果发现服务器出现异常,应该立即停止测试,并进行排查。
- 日志分析:仔细分析服务器的日志文件,例如 Nginx 的 access.log 和 error.log、Tomcat 的 catalina.out 等。通过日志,可以找到问题的根源。
- 模拟真实用户行为:在编写 JMeter 脚本时,尽量模拟真实用户的行为。例如,可以使用 Think Time 元素来模拟用户的思考时间,使用 Cookie 管理器来处理 Cookie 信息等。
- 考虑连接池耗尽问题: 除了服务器端,也要考虑 JMeter 本身httpClient连接池配置,避免JMeter自身因为连接池耗尽而无法发送请求。
总之,java.net.ConnectException: Connection refused: connect 异常是一个比较常见的问题,但只要我们掌握了正确的排查方法和优化技巧,就能有效地解决这个问题,并保证压力测试的顺利进行。
冠军资讯
代码一只喵