![](/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.