繁体   English   中英

在客户端重新启动之前,无法使用 docker-compose 访问 Spring Config 服务器

[英]Spring Config server not reachable with docker-compose until client is restarted

我对 Eureka、Config Server 和我的客户端进行了“发现优先”设置。

问题是这3个服务是按顺序启动的,但是client-server好像注册得太早了,一直找不到config-server。 我尝试过一个第三方库,它允许等待 config-server:8888 可用,但这似乎并不总是有效。 这类似于竞态条件。

解决方法是,如果我在一切都docker restartdocker restart客户端服务器,它会注册并找到 config-server 就好了。

首次运行docker-compose

Fetching config from server at : http://localhost:8888
Connect Timeout Exception on Url - http://localhost:8888. Will be trying the next url if available

当我docker restart客户端时:

Fetching config from server at : http://a80b001d04a7:8888/
Located environment: name=client-server, profiles=[default], label=null, version=053c8e1b14dc0281d5af0349c9b2cf012c1a346f, state=null

不确定我的 JAVA_OPTS 属性是不是从我的 docker-compose.yml 设置的不够快,或者有一些网络竞争条件,或者什么。 我已经在这个问题上来回反复太久了。

我的配置如下:

这是我的 docker-compose.yml:

version: '3'
services:
  eureka:
    image: eureka-server:latest
    environment:
    - "JAVA_OPTS=-DEUREKA_SERVER=http://eureka:8761/eureka"
    ports:
      - 8761:8761
  config:
    image: config-server:latest
    environment:
      - "JAVA_OPTS=-DEUREKA_SERVER=http://eureka:8761/eureka"
    depends_on:
      - eureka
    ports:
      - 8888:8888
  client:
    image: client-server:latest
    environment:
      JAVA_OPTS: -DEUREKA_SERVER=http://eureka:8761/eureka
    depends_on:
      - config
    ports:
      - 9000:9000

这是尤里卡服务器 application.yml:

server:
  port: 8761

spring:
  application:
    name: eureka-server

eureka:
  client:
    registerWithEureka: false
    fetchRegistry: false
    service-url:
      defaultZone: ${EUREKA_SERVER:http://localhost:8761/eureka}

这是配置服务器 bootstrap.yml:

server:
  port: 8888

eureka:
  client:
    serviceUrl:
      defaultZone: ${EUREKA_SERVER:http://localhost:8761/eureka}

spring:
  application:
    name: config-server

这是客户端-服务器 bootstrap.yml:

spring:
  application:
    name: client-server
  cloud:
    config:
      discovery:
        enabled: true
        serviceId: config-server
      fast-fail: true
    retry:
      max-attempts: 10000
      max-interval: 1000

eureka:
  instance:
    hostname: client-server
  client:
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      defaultZone: ${EUREKA_SERVER:http://localhost:8761/eureka}

编辑:

使用 docker-compose 等待库( https://github.com/ufoscout/docker-compose-wait ),我可以让客户端-服务器等待 eureka 和配置可用,然后等待 90 秒(Eureka 文档建议注册可能需要长达 90 秒),并且它似乎始终如一地工作。

这是一个可以接受的解决方案吗? 感觉有点像黑客。

作为纯粹主义者,您的问题的答案是否定的,这不是一个可接受的解决方案,因为正如此处所述,Docker 由于某种原因从 v3 中删除了healthcheck

Docker 有意识地决定不支持等待容器处于“就绪”状态的功能。 他们认为依赖于其他系统的应用程序应该能够抵御故障。

在同一链接中,描述了原因:

等待数据库(例如)准备就绪的问题实际上只是分布式系统更大问题的一个子集。 在生产中,您的数据库可能随时不可用或移动主机。 您的应用程序需要对这些类型的故障具有弹性。

要处理此问题,您的应用程序应尝试在失败后重新建立与数据库的连接。 如果应用程序重试连接,它最终应该能够连接到数据库。

那么基本上有以下三种选择:

  1. 将 v2.1 与healhcheck一起healhcheck 在此处查看示例
  2. 使用 v3 和像wait-for-itdockerize这样的工具,@ortomala-lokni 已经完美解释了
  3. 使您的应用程序对 config-server 故障具有弹性,并能够 config-client 在启动时重试连接

推荐和可接受的解决方案是 3)。 您可以使用此处提到的Spring Retry 找到下面的bootstrap.yml配置:

spring:
  application:
    name: config-client
  profiles:
     active: dev
  cloud:
    config:
     discovery:
       enabled: true
       service-id: config-server
     fail-fast: true
     retry:
       initial-interval: 1500
       multiplier: 1.5
       max-attempts: 10000
       max-interval: 1000

eureka:
  instance:
    hostname: config-client
  client:
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      defaultZone: ${EUREKA_SERVER:http://localhost:8761/eureka}

顺便说一句,我在您的弹簧配置中发现了一个错误。 它是fail-fast而不是fast-fail

请记住包含以下依赖项(如果您使用的是 gradle,则类似):

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>

您可以在这里找到一个很好的配置(和解释) 同时考虑了 Eureka 服务器中注册过程中的弹性。

当拥有微服务环境时,我们必须考虑我们的环境的弹性,因为像 config-service、discovery-service 这样的平台服务在短时间内不可用。

但我根本不是纯粹主义者,我不会删除人们正在使用的某些功能(这是一个自由的问题)。 因此,另一种解决方案是:

如果它对你有用,那么继续

因为我真的不明白为什么 Docker 会从 v3 中抑制出色的healthcheck命令。

正如 Carlos Cavero 所说,最好的解决方案可能是使您的应用程序对配置服务器故障具有弹性。 但是你也可以通过使用 Github 上Eficodewait-for脚本来解决这个问题。

将脚本复制到您的容器中,并在您docker-compose.yml使用:

client:
    image: client-server:latest
    environment:
      JAVA_OPTS: -DEUREKA_SERVER=http://eureka:8761/eureka
    depends_on:
      - config
    ports:
      - 9000:9000
    command: wait-for $CONFIGSERVER_SERVICE_NAME:$CONFIGSERVER_PORT -- java $JVM_OPTIONS -jar client.war $SPRING_OPTIONS

CONFIGSERVER_SERVICE_NAMECONFIGSERVER_PORT的环境变量可以在您的Docker Compose 环境文件中定义。

如果需要等待多个服务,可以合并这个pull request ,在命令行参数中列出所有需要的服务,例如:

command: wait-for $SERVICE1_NAME $SERVICE1_PORT $SERVICE2_NAME $SERVICE2_PORT -- java $JVM_OPTIONS -jar client.war $SPRING_OPTIONS

使用 docker-compose 时,服务依赖总是很棘手。

您的解决方案是可以接受的,因为“别无他法”。 为了避免第三方库,这就是我在同一场景中所做的:

在 Dockerfile 中,我添加netcat-openbsd ,一个我调用entrypoint的 bash 文件和应用程序 jar,然后我运行 entrypoint.sh。

FROM openjdk:8-jdk-alpine
RUN apk --no-cache add netcat-openbsd
COPY entrypoint.sh /opt/bin/
COPY app.jar /opt/lib/
RUN chmod 755 /opt/esusab-bi/bin/app/entrypoint.sh

入口点文件有以下指令:

#!/bin/sh

while ! nc -z config 8888 ; do
    echo "Waiting for upcoming Config Server"
    sleep 2
done

java -jar /opt/lib/app.jar

它会延迟应用程序的启动,直到您的配置服务器启动,没有特定的时间间隔。

只是一个友好的提示:您不应该将 Config 绑定到 Eureka,反之亦然 -> Eureka 应该是 Config 客户端。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM