ECONNREFUSED 连接被拒绝怎么排查?5 种原因一次讲清(含 Docker 场景)
现象:各种语言,同一个错
# Node.js
Error: connect ECONNREFUSED 127.0.0.1:3306
at TCPConnectWrap.afterConnect (node:net:1607:16)
# curl
curl: (7) Failed to connect to 127.0.0.1 port 6379: Connection refused
# Java
java.net.ConnectException: Connection refused (Connection refused)
一行结论:网络能到达那台机器,但你连的那个端口上没有任何进程在监听。操作系统直接回了个 RST(reset)拒绝连接——注意它和「超时」的区别:超时(ETIMEDOUT)是包根本到不了或被丢,拒绝(REFUSED)是到了但没人应答,这个区分直接决定排查方向。
| 报错 | 含义 | 大方向 | |---|---|---| | ECONNREFUSED | 到了,端口没人听 | 查服务/端口 | | ETIMEDOUT | 包没到或被丢 | 查网络/防火墙 |
五种原因,按概率排序
1. 服务压根没起来(最常见)
systemctl status mysql # Linux 服务
docker ps # 容器在跑吗?重启过吗?
brew services list # macOS
容器退出后自动重启失败是高频场景:docker ps -a 里看 STATUS 是 Restarting (1) 5 seconds ago 还是 Up。前者说明容器在崩溃循环,端口自然连不上。
2. 端口记错了
各服务默认端口速查:
| 服务 | 默认端口 | |---|---| | MySQL | 3306 | | PostgreSQL | 5432 | | Redis | 6379 | | MongoDB | 27017 | | Elasticsearch | 9200 | | RabbitMQ | 5672 |
两个易错点:Redis 配置里写的是 port 6379,但你用 --port 参数覆盖过;MySQL 改过 my.cnf 的 port=。以实际监听为准,别以记忆为准:
ss -tlnp | grep -E '3306|6379' # Linux
lsof -nP -iTCP:3306 -sTCP:LISTEN # macOS
3. 服务只监听了 127.0.0.1,你从别的机器连
ss -tlnp | grep 5432
# LISTEN 127.0.0.1:5432 ← 只接受本机连接
# LISTEN 0.0.0.0:5432 ← 接受任意来源
# LISTEN [::]:5432 ← IPv6 任意来源
如果是 127.0.0.1:端口,远程连接一律拒绝。修法按服务改监听地址:MySQL 注释掉 bind-address=127.0.0.1、PostgreSQL 改 listen_addresses = '*'、Redis 改 bind 0.0.0.0(同时务必配 requirepass,Redis 裸奔公网是勒索重灾区)。
4. Docker 场景:localhost 在容器里不是宿主机
容器内连宿主机上的服务,127.0.0.1 指的是容器自己,不是宿主机:
# 容器里的应用连数据库——两种正确姿势
# 姿势一:都在 docker network 里,用服务名(推荐)
spring.datasource.url: jdbc:mysql://interview-mysql:3306/mydb
# 姿势二:容器连宿主机上的服务
# macOS/Windows Docker Desktop 用专属域名:
jdbc:mysql://host.docker.internal:3306/mydb
# Linux 宿主机(Docker 20.10+)加 extra_hosts:
services:
app:
extra_hosts:
- "host.docker.internal:host-gateway"
反过来,宿主机连容器:必须依赖 docker run -p 127.0.0.1:3306:3306 这样的端口映射,没映射 -p,宿主机上 curl localhost:3306 必然 ECONNREFUSED。
5. 防火墙主动 REJECT
iptables 的 REJECT 规则会回 RST,表现和「没人监听」一模一样(DROP 才表现为超时):
sudo iptables -L -n | grep -i reject
云服务器还有一层安全组——阿里云/腾讯云控制台里的安全组规则没放行端口,表现也可能是拒绝或超时,且服务器内部 ss 看一切正常。这是「本地正常、上云就连不上」的经典原因。
排查路线(从下往上三层)
# 第一层:端口上有人听吗?
ss -tlnp | grep <端口>
# 第二层:本机能连通吗?
nc -zv 127.0.0.1 <端口>
# 第三层:目标机器/容器网络里能连通吗?
docker exec -it <容器> sh -c 'nc -zv <目标地址> <端口>'
第一层没人听 → 原因 1/2;本机能通远程不能 → 原因 3/5;容器里连不上 → 原因 4。三层走完,问题基本定位。
顺手区分:ECONNREFUSED vs EADDRINUSE
一个端口的两端视角:连接别人时被拒是 ECONNREFUSED(对面没人听);自己监听时被占是 EADDRINUSE(这端口已被别人占了)。后者的排查看这篇:端口被占用怎么办?EADDRINUSE 报错排查。
排查清单
docker ps/systemctl status— 服务活着吗?(含崩溃循环检查)ss -tlnp | grep <端口>— 实际监听端口和地址是什么?- 监听地址是
127.0.0.1还是0.0.0.0?远程连接必须后者 - Docker 里连宿主机服务:用
host.docker.internal,不是 localhost - 云服务器查安全组规则,服务器内查 iptables REJECT
- 分清 REFUSED(到了没人听)和 TIMEOUT(到不了),方向完全不同
本文由 ToolVault 工具匣 提供。相关工具:Dockerfile 生成器、CIDR 子网计算、API 在线测试。相关阅读:端口被占用 EADDRINUSE 排查。访问 首页 查看更多开发者工具。
相关工具
相关文章
Permission denied (publickey) 怎么解决?Git 推送失败的 6 种原因与修复
git clone/push 报 Permission denied (publickey) fatal: Could not read from remote repository?覆盖公钥没生成、没加载进 agent、没添加到 GitHub/Gitee、多账号配错密钥、deploy key 权限、remote URL 写错六种根因,附 ssh -v 诊断方法。
npm ERR! ERESOLVE:peer dependency 冲突的四种解决策略
npm install 报 ERESOLVE unable to resolve dependency tree 怎么办?理解 peer dependency 的设计意图,掌握四种解决策略(版本修复 / legacy-peer-deps / overrides / dedupe)及其适用场景与风险。
error:0308010C digital envelope routines::unsupported 怎么解决?Node 17+ 跑老项目的三种修法
Node 17+ 启动 webpack 4 老项目报 error:0308010C:digital envelope routines::unsupported?根因是 OpenSSL 3.0 移除了 MD4 哈希。本文给出 --openssl-legacy-provider 临时方案、升级 webpack 5 根治方案和锁定 Node 16 的取舍。