You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Docker中Spring Boot微服务RestTemplate请求连接拒绝问题排查

问题分析与解决方案

让我帮你拆解一下这个连接拒绝的问题,其实核心是两个容易踩的Docker Compose坑:

1. 容器间通信要用内部端口,不是宿主机映射端口

你现在的请求地址http://product:8083/api/products/犯了一个常见错误:容器之间的通信是直接走容器内部的端口,而不是你在ports里配置的宿主机映射端口

看你的docker-compose.yml配置:

product:
  image: product-service
  ports:
    - 8083:8080

这里的8083:8080是把容器内部的8080端口映射到宿主机的8083端口,方便你从宿主机访问服务。但api容器和product容器在同一个Docker网络里,直接用服务名product访问时,应该用容器内部的8080端口,而非外部映射的8083

同时你的api服务里的环境变量SERVICE_PORT_PRODUCT=8083也配反了,应该改成8080

2. depends_on只保证启动顺序,不保证服务就绪

你的api服务配置了depends_on: [product],这只会让Docker先启动product容器,再启动api容器,但不保证product里的Spring Boot服务已经完全初始化完成。如果api服务启动后立刻发起请求,这时候product的服务可能还没完成启动,就会出现连接拒绝。


修复步骤

第一步:修正端口配置

修改docker-compose.yml里api服务的环境变量,同时调整代码中的请求地址:

api:
  image: api-service
  container_name: api-service
  restart: always
  depends_on:
    - product
  ports:
    - 8081:8080
  environment:
    - SERVICE_PORT_PRODUCT=8080 # 改成容器内部端口
product:
  image: product-service
  container_name: product-service
  restart: always
  ports:
    - 8083:8080

然后在api服务的代码里,把请求地址改成http://product:${SERVICE_PORT_PRODUCT}/api/products/(确保正确读取环境变量),或者直接写死http://product:8080/api/products/

第二步:处理服务就绪问题

有几种实用方式解决这个问题:

  • 添加重试逻辑:在Spring Boot里用@Retryable注解给RestTemplate的请求方法添加重试,比如失败后重试3次,每次间隔1秒,直到product服务就绪。
  • 使用等待工具:在api服务的启动脚本里加入wait-for-it.sh(或类似工具),等待product:8080端口可连接后再启动Spring Boot服务。
  • 配置健康检查:给product服务添加Docker健康检查,让Docker确认服务就绪后再允许api服务启动(需要Docker Compose版本支持):
    product:
      image: product-service
      container_name: product-service
      restart: always
      ports:
        - 8083:8080
      healthcheck:
        test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] # 假设你开启了Spring Boot Actuator健康端点
        interval: 5s
        timeout: 3s
        retries: 5
    api:
      # 其他配置...
      depends_on:
        product:
          condition: service_healthy # 等待product服务健康检查通过
    

额外检查点

  • 确认product服务的容器内部确实在监听8080端口:执行docker exec product-service netstat -tulpn | grep 8080,如果能看到监听记录就没问题。
  • 确认两个服务在同一个Docker网络:默认情况下Docker Compose会创建一个默认网络,所有服务都在里面,如果你自定义了网络,要确保两个服务都加入同一个网络。

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

火山引擎 最新活动