Spring Cloud 数据流微服务无法访问 Docker Compose 配置服务器

问题描述

可以从 localhost:8888 访问配置服务器,但是当我在 SCDF 上部署我的应用程序时出现以下错误

Fetching config from server at : http://localhost:8888
2021-07-30 14:58:53.535  INFO 143 --- [           main] o.s.b.context.config.ConfigDataLoader    : Connect Timeout Exception on Url - http://localhost:8888. Will be trying the next url if available
2021-07-30 14:58:53.535  WARN 143 --- [           main] o.s.b.context.config.ConfigDataLoader    : Could not locate PropertySource ([configserverConfigDataResource@3de88f64 uris = array<String>['http://localhost:8888'],optional = true,profiles = list['default']]): I/O error on GET request for "http://localhost:8888/backend-service/default": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)

除了配置服务器连接之外,应用程序在 SCDF 上成功部署。我在 SCDF 中指定的唯一属性是 docker 网络。我正在使用 spring.config.import 并且没有使用任何引导程序。这在本地部署时一切正常,但在 SCDF 上部署时,微服务无法连接到配置服务器。

Spring Boot 版本:2.5.1

应用属性

spring.application.name=backend-service
spring.cloud.config.fail-fast=true
spring.cloud.config.retry.max-attempts=6
spring.cloud.config.retry.max-interval=11000
spring.config.import=optional:configserver:http://localhost:8888

配置服务器属性

spring.cloud.config.server.git.uri=...
management.endpoints.web.exposure.include=*
spring.cloud.config.fail-fast=true
spring.cloud.config.retry.max-attempts=6
spring.cloud.config.retry.max-interval=11000
spring.cloud.bus.id=my-config-server
spring.cloud.stream.rabbit.bindings.springCloudBus.consumer.declareExchange=false
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.cloud.bus.enabled=true
spring.cloud.bus.refresh.enabled: true
spring.cloud.bus.env.enabled: true
server.port=8888

docker-compose.yml

version: '3.1'

services:

  h2:
    ...

  rabbitmq-container:
    image: rabbitmq:3.7.14-management
    hostname: dataflow-rabbitmq
    expose:
      - '5672'
    ports:
      - "5672:5672"
      - "15672:15672"
    networks:
      - scdfnet

  dataflow-server:
    ...
    networks:
      - scdfnet

  app-import:
    ...
    networks:
      - scdfnet 
  skipper-server:
    ...
    networks:
      - scdfnet

  configserver-container:
    image: ...
    ports:
      - "8888:8888"
    expose:
      - '8888'
    environment:
      - spring_rabbitmq_host=rabbitmq-container
      - spring_rabbitmq_port=5672
      - spring_rabbitmq_username=guest
      - spring_rabbitmq_password=guest
    depends_on:
      - rabbitmq-container
    networks:
      - scdfnet

networks:
  scdfnet:
    external:
      name: scdfnet

volumes:
     h2-data:

解决方法

对于遇到此问题的其他人,我找到了两种解决方法。问题在于,一旦 Spring Boot 应用程序被容器化,属性文件中引用的 localhost 将导致程序获取应用程序容器虚拟网络的 localhost,而不是本地机器的 localhost。

针对相同的错误有许多 Stack Overflow 的答案,但都围绕着对引导程序属性的更正。但是,自 Spring Boot 2.4 起不推荐使用 bootstrap 上下文初始化。

第一个解决方案是使用您的 IPv4 地址而不是 localhost。

spring.config.import=configserver:http://<insert IPv4 address>:8888

例如:

spring.config.import=configserver:http://10.6.39.148:8888

比硬接线地址更好的解决方案是引用在 docker compose 中运行的配置服务器容器:

spring.config.import=optional:configserver:http://configserver-container:8888

确保所有 Docker Compose 服务都在同一网络上运行(在我的情况下为 scdf_network),并注意此地址仅在 docker-compose 上运行时才有效,因此如果您在 Eclipse 上构建 maven 文件,您可能需要删除或禁用您的测试才能成功构建。这可能是不必要的;可能只是我未能将某些属性复制到我的本地 application.properties 文件,这导致上下文测试失败。根据 documentationoptional 标签应该允许配置客户端运行,即使无法与配置服务器建立联系。