![](/img/trans.png)
[英]Using external config in spring boot application within docker-compose
[英]Spring Config server not reachable with docker-compose until client is restarted
我對 Eureka、Config Server 和我的客戶端進行了“發現優先”設置。
問題是這3個服務是按順序啟動的,但是client-server好像注冊得太早了,一直找不到config-server。 我嘗試過一個第三方庫,它允許等待 config-server:8888 可用,但這似乎並不總是有效。 這類似於競態條件。
解決方法是,如果我在一切都docker restart
后docker 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 有意識地決定不支持等待容器處於“就緒”狀態的功能。 他們認為依賴於其他系統的應用程序應該能夠抵御故障。
在同一鏈接中,描述了原因:
等待數據庫(例如)准備就緒的問題實際上只是分布式系統更大問題的一個子集。 在生產中,您的數據庫可能隨時不可用或移動主機。 您的應用程序需要對這些類型的故障具有彈性。
要處理此問題,您的應用程序應嘗試在失敗后重新建立與數據庫的連接。 如果應用程序重試連接,它最終應該能夠連接到數據庫。
那么基本上有以下三種選擇:
healhcheck
一起healhcheck
。 在此處查看示例推薦和可接受的解決方案是 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 上Eficode的wait-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_NAME
和CONFIGSERVER_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.