报错 "dial tcp 127.0.0.1:9443: connect: connection refused" 怎么排查
connection refused 表示目标端口没有进程在监听(与超时的"被丢包"不同)。按四步排查:进程是否在跑、监听端口对不对、防火墙是否拦截、URL 是否写错。附 Prometheus metrics 抓取场景的具体修法。
一句话回答:connection refused 的含义非常明确——连接尝试被主动拒绝,常见原因是目标端口没有监听**、连接到错误的地址/命名空间,也可能是防火墙 REJECT。超时则表示规定时间内未完成连接,不足以单凭错误断定某个防火墙丢包。排查四板斧:确认服务进程在运行 → 确认它监听的端口和地址 → 确认防火墙/安全组放行 → 确认客户端 URL 写对。**
第一步:服务到底在不在跑
ps aux | grep prometheus # 以 Prometheus 为例,换成你的进程名
systemctl status prometheus # systemd 管理的服务
没在跑就启动:systemctl start prometheus 或 ./prometheus --config.file=prometheus.yml。
第二步:进程监听了哪个端口和地址
ss -tlnp | grep 9443 # 或 netstat -tlnp
关键看监听地址:
127.0.0.1:9443—— 只接受本机连接,容器外/其他机器连进来一律 refused0.0.0.0:9443—— 接受所有网卡的连接- 列表里根本没有 9443 —— 服务监听了别的端口,查配置文件(如 Prometheus 的
--web.listen-address)
第三步:防火墙与安全组
sudo iptables -L -n # 查看规则
sudo ufw status # Ubuntu
# 仅在确认需要远程访问时,对指定来源放行(按实际可信IP替换)
sudo ufw allow from 192.0.2.10 to any port 9443 proto tcp
云服务器还要检查安全组(控制台里的入站规则)——系统防火墙放开但安全组没放,外部照样连不上。注意:安全组拦截通常表现为超时而非 refused,refused 大概率还是端口没监听。
第四步:客户端 URL 对不对
- 端口写错(9443 vs 9090):Prometheus 默认端口是 9090,不是 9443
- 协议写错:目标是 http 却写了
https:// - Docker/K8s 环境:
localhost指的是当前网络命名空间;普通容器通常独立,Kubernetes 同一 Pod 的容器共享网络;host 网络模式另当别论——要用服务名或容器 IP
例如 DataKit 访问 Exporter 被拒绝时,应在 DataKit 所在的网络命名空间测试目标地址;宿主机访问成功不代表容器中的采集器也能访问。
refused 与 timeout 对照
| 现象 | 含义 | 排查方向 |
|---|---|---|
| connection refused | 主机可达,端口无监听(或 iptables REJECT) | 进程、监听地址 |
| 超时(timeout) | 在时限内未建连,可能丢包、路由问题或服务负载等 | 结合抓包、两端日志与网络路径排查 |
| no route to host | 路由层面不可达 | 网络配置、网关 |
常见问题(FAQ)
Q:curl localhost:9443 通,别的机器连不通?
A:服务监听在 127.0.0.1,只接受本机连接。改配置监听 0.0.0.0(并评估暴露风险),或在前面加反向代理。
Q:Docker 容器里连宿主机的 localhost 不通?
A:容器里的 localhost 是容器自身。连宿主机用 host.docker.internal(Mac/Windows)或 --add-host/宿主机网卡 IP(Linux);容器间互连用 Compose/K8s 的服务名。
Q:进程在跑、端口在听、防火墙也放了,还是 refused?
A:检查是否走了代理(http_proxy 环境变量把 localhost 也代理了——给 no_proxy 加上 localhost,127.0.0.1);以及是否连错了机器/命名空间(K8s 里连到了别的 Pod)。
核查依据
本文依据官方文档核对,示例未在实际业务环境运行;上线前请按部署版本、权限与数据范围验证。