You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java在Docker容器间调用HttpURLConnection报Connection refused如何解决?

问题排查与解决方案

这个现象的核心是容器网络层面连通性正常,但Java进程内部请求失败,按优先级排查以下原因即可:

常见原因1:Java进程读取了代理配置

大部分容器环境会默认设置http_proxy/https_proxy全局环境变量,JDK默认会自动读取这些环境变量作为全局HTTP代理。容器内部的服务域名(比如另一个容器的名称)不会走代理规则,会被直接转发到代理服务器,自然无法连通。

  • 排查方式:在调用请求的代码前增加日志打印,输出以下系统属性:
System.out.println("http.proxyHost: " + System.getProperty("http.proxyHost"));
System.out.println("http.proxyPort: " + System.getProperty("http.proxyPort"));
System.out.println("Request URL: " + myUrl);

确认请求的URL和你wget使用的完全一致,同时没有配置多余的代理。

  • 解决方案:如果确实存在代理配置,可以在Java启动参数中增加配置,排除容器内部域名的代理:
-Dhttp.nonProxyHosts="第二个容器名|localhost|127.0.0.1"

常见原因2:请求调用时机早于第二个服务就绪

从报错栈可以看出,请求是在Spring Bean初始化阶段触发的,属于第一个服务的启动流程。docker-compose的depends_on配置只能保证容器的启动顺序,无法保证第二个容器内部的Spring Boot应用完全启动完成、端口进入监听状态。你手动进入容器执行wget的时候,两个服务都已经完成启动,所以能正常访问,但启动阶段的调用就会失败。

  • 解决方案:
    • 给第二个容器配置健康检查,第一个容器等待第二个容器健康检查通过后再启动;
    • 在请求代码中增加3-5次重试逻辑,每次间隔1-2秒,兼容服务启动的时间差;
    • 调整代码逻辑,不要在Bean初始化阶段发起跨服务调用,改成第一次使用时懒加载调用。

常见原因3:JVM网络协议优先级问题

部分JDK版本默认优先使用IPv6协议栈,而Docker容器内部网络默认是IPv4,会导致域名解析异常。

  • 解决方案:在第一个服务的Java启动参数中增加以下配置:
-Djava.net.preferIPv4Stack=true

其他排查方向

如果以上方案都无效,可以替换HTTP客户端验证:JDK自带的HttpURLConnection本身存在很多历史问题,换成Spring自带的RestTemplate或者OkHttp客户端发送请求,排除原生客户端的兼容性问题。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.19 05:06:04