java.net.ConnectException: Connection refused报错的解决方法详解

 更新时间:2026年05月09日 08:27:10   作者:李少兄  
这篇文章主要为大家详细介绍了Java开发中常见的java.net.ConnectException(连接被拒绝)异常,从操作系统层面解析其本质,详细分析了常见原因和解决方法,希望对大家有所帮助

前言:一个高频却常被误解的异常

在 Java 企业级应用开发中,无论是构建 Web 后端服务、微服务架构,还是进行数据集成与批处理任务,开发者几乎不可避免地会遇到如下异常堆栈:

java.net.ConnectException: Connection refused: connect
    at java.base/sun.nio.ch.Net.connect0(Native Method)
    at java.base/sun.nio.ch.Net.connect(Net.java:589)
    at java.base/sun.nio.ch.Net.connect(Net.java:578)
    at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:583)
    at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
    at java.base/java.net.Socket.connect(Socket.java:751)
    ...

该异常通常出现在尝试建立 TCP 连接时——例如通过 JDBC 连接 MySQL、调用 RESTful API、连接 Redis 缓存、或与消息队列(如 RabbitMQ、Kafka)通信。尽管其字面意思看似直白(“连接被拒绝”),但许多开发者在初次遭遇时仍会陷入困惑:是代码写错了?是网络不通?还是服务宕机了?

一、问题本质:操作系统层面的“拒绝”信号

1.1 异常来源并非 Java 虚拟机

首先必须明确:java.net.ConnectException 是 Java 对底层操作系统返回错误码的封装。当 Java 应用调用 Socket.connect() 方法时,JVM 会委托操作系统内核发起 TCP 连接请求。若内核在尝试建立连接过程中收到特定的网络响应(如 RST 包),便会向 JVM 返回一个错误码(在 Linux/Unix 系统中为 ECONNREFUSED,在 Windows 中为 WSAECONNREFUSED),JVM 再将其转换为 ConnectException 抛出。

因此,该异常反映的是网络层或传输层的问题,而非应用逻辑错误

1.2 TCP 三次握手中的“拒绝”机制

理解此异常的关键在于掌握 TCP 协议的行为:

  • 当客户端向目标主机的某端口发送 SYN(同步)包以发起连接时;
  • 若目标主机的操作系统内核发现没有任何进程正在监听该端口
  • 内核将立即向客户端回送一个 RST(Reset)包,表示“此端口无服务,请勿重试”;
  • 客户端操作系统收到 RST 后,向上层应用(即 Java 程序)报告“Connection refused”。

核心结论Connection refused = 目标主机可达 + 目标端口无服务监听

这与 Connection timed out(连接超时)有本质区别:

  • Timeout:SYN 包发出后未收到任何响应(可能因网络中断、防火墙丢包、主机宕机);
  • Refused:SYN 包已送达,但对方明确告知“此处无服务”。

二、根本原因分类与排查指南

根据多年工程实践经验,导致 Connection refused 的原因可归纳为以下五大类。

2.1 服务进程未启动(最常见原因)

这是本地开发、测试环境中占比最高的原因。服务未运行,自然无法监听端口。

Windows 系统操作指南

在 Windows 操作系统中,MySQL、PostgreSQL、Redis 等数据库服务通常以“Windows 服务”的形式安装和管理。如果服务未启动,则对应的端口(如 MySQL 默认 3306)将不会被监听,从而导致 Connection refused 错误。

图形化界面操作步骤(推荐初学者使用)

  1. 打开“服务”管理控制台

    • 按下键盘上的 Win + R 组合键,弹出“运行”对话框。
    • 在输入框中键入 services.msc,然后按回车键或点击“确定”。
    • 此时将打开“服务”窗口,其中列出了当前系统中所有已注册的服务。
  2. 查找目标数据库服务

    • 在服务列表中,滚动查找名称包含 MySQL 的条目。
    • 常见的服务名称包括:
      • MySQL80(MySQL 8.0 版本)
      • MySQL57(MySQL 5.7 版本)
      • MySQL(通用名称,多见于旧版安装)
      • MariaDB(MariaDB 数据库)
      • Redis(Redis 服务)
    • 如果你不确定具体名称,可以右键点击任意服务 → “属性”,查看“路径到可执行文件”字段,确认是否为你安装的数据库程序。
  3. 检查服务状态并启动

    • 查看“状态”列。如果该列为空白,说明服务当前未运行
    • 右键点击该服务名称,在弹出的上下文菜单中选择“启动”。
    • 启动成功后,“状态”列将显示为“正在运行”。
    • 如果启动失败(例如提示“错误 1067:进程意外终止”),则需进一步检查数据库的日志文件(通常位于 C:\ProgramData\MySQL\MySQL Server X.X\Data\ 目录下的 .err 文件)。
  4. 设置开机自动启动(可选)

    • 为避免每次重启电脑后手动启动服务,可右键点击服务 → “属性”。
    • 在“启动类型”下拉菜单中选择“自动”。
    • 点击“应用”并“确定”。下次系统启动时,该服务将自动运行。

命令行方式(适用于脚本化或高级用户)

Windows 提供了强大的命令行工具来管理服务,无需依赖图形界面。

1.列出所有与 MySQL 相关的服务

sc queryex type= service state= all | findstr /i "mysql"
  • sc(Service Control)是 Windows 内置的服务管理命令。
  • 此命令将输出所有服务名中包含“mysql”(不区分大小写)的服务及其状态。

2.启动指定服务

net start MySQL80
  • MySQL80 替换为你实际的服务名称。
  • 成功启动后,命令行会显示“MySQL80 服务正在启动… MySQL80 服务已经启动成功。”

3.停止服务

net stop MySQL80

4.查询服务详细信息

sc qc MySQL80

此命令可查看服务的可执行文件路径、依赖关系、启动账户等关键信息,对排错非常有帮助。

macOS 系统操作指南

macOS 上的数据库服务管理方式取决于其安装途径。主流方式有两种:Homebrew(开发者首选)和 官方 .dmg 安装包

A. 通过 Homebrew 安装的 MySQL(强烈推荐)

Homebrew 是 macOS 上最流行的包管理器,它能自动处理依赖、配置和后台服务管理。

检查 Homebrew 服务状态:打开“终端”(Terminal),输入以下命令:

brew services list

该命令会列出所有由 Homebrew 管理的后台服务。

输出示例:

Name    Status  User     Plist
mysql   stopped          /Users/yourname/Library/LaunchAgents/homebrew.mxcl.mysql.plist
redis   started yourname /Users/yourname/Library/LaunchAgents/homebrew.mxcl.redis.plist

Status 列显示 stopped 表示服务未运行。

启动 MySQL 服务

# 启动服务,并设置为登录时自动启动(仅对当前用户)
brew services start mysql
# 或者,仅启动一次(不设为自动启动)
brew services run mysql

start 命令会创建一个 launchd 配置文件(.plist),确保服务在用户登录时自动启动。

run 命令则只在当前终端会话中运行服务,关闭终端后服务也会停止。

停止服务

brew services stop mysql

验证服务是否正常运行

# 检查 MySQL 进程
ps aux | grep mysqld
# 尝试连接数据库(默认 root 用户无密码,首次安装后建议运行 mysql_secure_installation)
mysql -u root

查看日志(排错必备):Homebrew 安装的 MySQL 日志通常位于:

cat /opt/homebrew/var/mysql/$(hostname).err
# 或 Intel Mac:
cat /usr/local/var/mysql/$(hostname).err

B. 通过官方 .dmg 安装包安装的 MySQL

这种方式会将 MySQL 安装到 /usr/local/mysql/ 目录,并提供一个系统偏好设置面板。

图形化启动方式

  • 打开“系统设置”(System Settings)或旧版的“系统偏好设置”(System Preferences)。
  • 在底部或侧边栏找到并点击 “MySQL” 图标。
  • 在弹出的窗口中,你会看到一个大按钮:“Start MySQL Server”。
  • 点击该按钮,状态会从 “MySQL Server is stopped.” 变为 “MySQL Server is running.”。

命令行启动/停止:官方安装包提供了便捷的脚本:

# 启动 MySQL
sudo /usr/local/mysql/support-files/mysql.server start
# 停止 MySQL
sudo /usr/local/mysql/support-files/mysql.server stop
# 重启 MySQL
sudo /usr/local/mysql/support-files/mysql.server restart
# 检查状态
sudo /usr/local/mysql/support-files/mysql.server status
  • 这些命令本质上是调用了 mysqld_safe 脚本来管理进程。
  • 注意:需要 sudo 权限,因为服务通常以 _mysql 用户身份运行。

添加 PATH(方便使用 mysql 命令):为了能在任意目录下直接使用 mysql 命令,需要将 MySQL 的 bin 目录加入环境变量。

编辑你的 shell 配置文件(如 ~/.zshrc~/.bash_profile):

echo 'export PATH="/usr/local/mysql/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

之后即可直接在终端输入 mysql -u root -p 进行连接。

Linux 系统操作指南

Linux 发行版众多,但现代主流发行版(如 Ubuntu 16.04+、CentOS 7+、Debian 8+)均采用 systemd 作为初始化系统和服务管理器。旧版系统(如 CentOS 6)则使用 SysV init

A. 使用 systemd(现代 Linux 发行版标准)

systemd 通过 systemctl 命令统一管理所有系统服务。

检查 MySQL 服务状态:不同发行版对 MySQL 服务的命名略有差异:

执行以下命令之一:

# Ubuntu/Debian
sudo systemctl status mysql
# CentOS/RHEL
sudo systemctl status mysqld

Ubuntu/Debian 系:服务名为 mysql

CentOS/RHEL/Fedora 系:服务名为 mysqld

关键观察点

  • Active: active (running):服务正在运行。
  • Active: inactive (dead):服务已停止。
  • 如果提示 Unit ... not found,说明 MySQL 未安装。

启动、停止、重启服务

# 启动服务
sudo systemctl start mysql        # 或 mysqld
# 停止服务
sudo systemctl stop mysql
# 重启服务(修改配置后常用)
sudo systemctl restart mysql
# 重新加载配置(不中断服务)
sudo systemctl reload mysql

设置开机自启

# 启用开机自启
sudo systemctl enable mysql
# 禁用开机自启
sudo systemctl disable mysql

enable 命令会在 /etc/systemd/system/multi-user.target.wants/ 目录下创建一个符号链接。

查看实时服务日志(排错神器):systemd 集成了日志系统 journald,可通过以下命令实时跟踪服务日志:

# 实时跟踪 MySQL 服务日志
sudo journalctl -u mysql -f
# 查看最近 100 行日志
sudo journalctl -u mysql -n 100

这比直接查看 /var/log/mysql/error.log 更方便,因为它包含了 systemd 的元数据(如时间戳、进程ID)。

B. 使用 SysV init(旧版 Linux 系统)

虽然已逐渐被淘汰,但在一些遗留系统中仍会遇到。

检查服务状态

sudo service mysql status
# 或直接调用 init 脚本
sudo /etc/init.d/mysql status

管理服务

# 启动
sudo service mysql start
# 停止
sudo service mysql stop
# 重启
sudo service mysql restart

设置开机自启

# Ubuntu/Debian (使用 update-rc.d)
sudo update-rc.d mysql defaults
# CentOS 6 (使用 chkconfig)
sudo chkconfig --level 35 mysql on

2.2 客户端连接配置错误

连接字符串(URL)中的 IP 地址、端口号或协议写错。

常见错误示例

  • JDBC URL:jdbc:mysql://localhost:3360/testdb(端口应为 3306);
  • 主机名拼写错误:locahost127.0..1
  • 使用了错误的环境变量(如 DB_HOST=prod-db 但在 dev 环境运行)。

排查重点

  • 检查 application.properties / application.yml
  • 核对 .env 文件或 Kubernetes ConfigMap;
  • 在 IDE 中打印完整的连接 URL(注意脱敏)。

2.3 服务绑定地址限制(Bind Address Issue)

服务虽已启动,但仅绑定到 127.0.0.1(loopback 接口),拒绝来自外部 IP 的连接。

典型表现

  • 本机可通过 127.0.0.1:3306 连接 MySQL;
  • 但从同一局域网的另一台机器使用 192.168.1.100:3306 连接失败,报 Connection refused

验证命令(在服务所在主机执行):

ss -tuln | grep :3306
# 或
netstat -tuln | grep :3306

输出示例

  • tcp LISTEN 0 80 127.0.0.1:3306 0.0.0.0:*仅本机可连
  • tcp LISTEN 0 80 0.0.0.0:3306 0.0.0.0:*所有接口可连

解决方案

  • MySQL:修改 my.cnf(位置通常为 /etc/mysql/my.cnf/etc/my.cnf),在 [mysqld] 部分添加或修改 bind-address = 0.0.0.0,然后重启服务。
  • Spring Boot:添加 server.address=0.0.0.0 到配置文件。
  • 自定义服务:确保 ServerSocket 绑定到 0.0.0.0 或具体网卡 IP。

2.4 防火墙或安全组策略拦截

虽然服务在监听,但网络中间设备阻止了连接请求。

本地防火墙

Windows:检查“Windows Defender 防火墙” -> “高级设置” -> “入站规则”,确保有允许目标端口(如 3306)的规则。

Linux (UFW)

sudo ufw status verbose
sudo ufw allow 3306/tcp

Linux (firewalld)

sudo firewall-cmd --list-ports
sudo firewall-cmd --permanent --add-port=3306/tcp
sudo firewall-cmd --reload

云平台安全组(极易被忽视!):

  • 阿里云/腾讯云/AWS/Azure:登录控制台,找到你的云服务器实例,进入“安全组”配置页面。
  • 添加一条入站规则:协议类型 TCP,端口范围 3306,授权对象 0.0.0.0/0(测试用)或你的办公 IP。

2.5 容器化环境网络配置问题

在 Docker、Kubernetes 等容器平台中,网络命名空间隔离增加了复杂性。

Docker 常见问题

  • 未使用 -p 参数映射端口:docker run mysql ❌ vs docker run -p 3306:3306 mysql ✅;
  • 容器间通信使用了宿主机 IP 而非 Docker 自定义网络中的服务名。

Kubernetes 问题

  • Service 的 targetPort 与 Pod 实际监听端口不一致;
  • Pod 未通过 Readiness Probe,Service 未将流量转发;
  • NetworkPolicy 限制了跨命名空间通信。

排查命令

docker ps                          # 查看运行容器
docker port <container_id>         # 检查端口映射
kubectl get svc,pods -n <namespace> # 查看 K8s 服务状态

三、标准化排查流程(推荐顺序)

遵循 “由近及远、由内到外、先服务后网络” 的原则,逐步缩小问题范围。

步骤 1:确认目标服务是否真正运行并监听端口

操作位置:服务所在主机

# 检查进程
ps aux | grep <service_name>
# 检查端口监听(关键!)
ss -tuln | grep :<PORT>
# 或
netstat -tuln | grep :<PORT>
  • 若无输出 → 服务未启动或未监听该端口 → 启动服务。
  • 若输出显示 127.0.0.1:<PORT> → 仅本地可连 → 修改绑定地址。

步骤 2:核对客户端连接配置

操作位置:客户端代码/配置文件

  • 检查 JDBC URL、HTTP endpoint、Redis 连接字符串等;
  • 确保 IP、端口、协议(如 jdbc:mysql://)完全正确;
  • 注意环境变量覆盖问题(如 SPRING_DATASOURCE_URL)。

步骤 3:使用telnet或nc测试 TCP 连通性

操作位置:客户端主机

telnet <IP> <PORT>
# 或
nc -vz <IP> <PORT>
  • 成功:屏幕变黑或显示服务 banner(如 MySQL 版本信息);
  • Connection refused:服务未监听(回到步骤 1);
  • Timeout:网络不通或防火墙拦截(进入步骤 4)。

提示:Windows 可启用 Telnet 客户端功能,或使用 PowerShell 命令:

Test-NetConnection -ComputerName 127.0.0.1 -Port 3306

步骤 4:检查防火墙与云安全组

操作位置:服务所在主机 + 云控制台

  • 临时关闭本地防火墙测试;
  • 登录云平台控制台,检查实例关联的安全组规则;
  • 确保入站规则允许 <PORT>/TCP 来自你的 IP 或 0.0.0.0/0(测试用)。

步骤 5:容器环境专项检查

操作位置:Docker Host / Kubernetes Cluster

  • 确认容器运行状态:docker ps / kubectl get pods
  • 检查端口映射:docker port <id>
  • 在容器内部测试连接:docker exec -it <container> telnet 127.0.0.1 <PORT>

四、预防措施与工程最佳实践

4.1 自动化依赖管理

使用 docker-compose.yml 统一管理本地开发依赖(MySQL、Redis、Elasticsearch 等),避免手动启停遗漏。

version: '3'
services:
  mysql:
    image: mysql:8.0
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root

4.2 健康检查与启动探针

在应用启动时加入数据库连接探针,失败时提供友好提示:

@PostConstruct
public void checkDatabaseConnection() {
    try (Connection conn = dataSource.getConnection()) {
        // 成功
    } catch (SQLException e) {
        log.error("无法连接数据库,请检查服务是否启动及配置是否正确", e);
        System.exit(1); // 或抛出自定义异常
    }
}

4.3 配置分离与环境隔离

  • 使用 Spring Profiles、Kubernetes ConfigMap/Secrets 管理不同环境配置;
  • 避免硬编码连接信息,全部通过配置注入。

4.4 日志增强与可观测性

在捕获 ConnectException 时,记录完整的连接目标(脱敏后):

log.error("连接 {} 失败", maskUrl(url), e);

集成 APM 工具(如 SkyWalking、Prometheus)监控服务依赖健康状态。

4.5 基础设施即代码(IaC)

使用 Terraform、Ansible 管理云资源与安全组,确保网络策略可版本化、可审计。

以上就是java.net.ConnectException: Connection refused报错的解决方法详解的详细内容,更多关于java.net.ConnectException报错解决的资料请关注脚本之家其它相关文章!

相关文章

  • springboot整合shiro之thymeleaf使用shiro标签的方法

    springboot整合shiro之thymeleaf使用shiro标签的方法

    Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可以完全替代 JSP ,这篇文章主要介绍了springboot整合shiro之thymeleaf使用shiro标签的相关知识,需要的朋友可以参考下
    2021-10-10
  • mybatis的association传递参数问题示例

    mybatis的association传递参数问题示例

    这篇文章主要介绍了mybatis的association传递参数问题,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12
  • IDEA下使用MyBatisCodeHelper插件的方法详解

    IDEA下使用MyBatisCodeHelper插件的方法详解

    这篇文章主要介绍了IDEA下使用MyBatisCodeHelper插件的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • Mybatis如何获取最新插入数据的id

    Mybatis如何获取最新插入数据的id

    这篇文章主要介绍了Mybatis如何获取最新插入数据的id,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • 利用Stream聚合函数如何对BigDecimal求和

    利用Stream聚合函数如何对BigDecimal求和

    这篇文章主要介绍了利用Stream聚合函数如何对BigDecimal求和问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • Mybatis基于MapperScan注解的动态代理加载机制详解

    Mybatis基于MapperScan注解的动态代理加载机制详解

    这篇文章主要介绍了Mybatis基于MapperScan注解的动态代理加载机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2023-01-01
  • java中获取当前服务器的Ip地址的方法

    java中获取当前服务器的Ip地址的方法

    本篇文章主要介绍了java中获取当前服务器的Ip地址的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • 揭秘springboot中Redisson 可重入锁的实现原理

    揭秘springboot中Redisson 可重入锁的实现原理

    本文探究基于 Redisson 的可重入锁原理,通过使用 hash 数据结构 + Lua 脚本实现可重入的分布式锁,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-02-02
  • IDEA高效查看源码的快捷键及小技巧

    IDEA高效查看源码的快捷键及小技巧

    本篇文章这一部分的内容主要为大家介绍了一些平时看源码的时候常用的快捷键/小技巧!非常好用!掌握这些快捷键/小技巧,看源码的效率提升一个等级
    2022-01-01
  • Java中用爬虫进行解析的实例方法

    Java中用爬虫进行解析的实例方法

    在本篇文章里小编给大家整理的是一篇关于Java中用爬虫进行解析的实例方法,有需要的朋友们可以学习参考下。
    2020-12-12

最新评论