簡體   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