Eureka、Config Server、およびクライアントで「ディスカバリーファースト」の設定をしています。
問題は、これらの3つのサービスが順番に開始することですが、クライアントサーバーは登録が早すぎるようで、構成サーバーを見つけることができません。 config-server:8888が利用可能になるまで待機できるサードパーティのライブラリを試しましたが、それでも常に機能するとは限りません。競合状態に似ています。
回避策は、すべてが起動した後でクライアントサーバーを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
これはeureka-server 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}
これがconfig-server 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秒かかることが示されています)、それは一貫して機能しているようです。
これは許容できる解決策ですか?少しハックのように感じます。
あなたの質問に対する純粋な答えは[〜#〜] no [〜#〜]です、それは受け入れられる解決策ではありません。 ここ 、Dockerは何らかの理由でv3からhealthcheck
を削除しました:
Dockerは、コンテナーが「準備完了」状態になるのを待つ機能をサポートしないことを意識的に決定しました。彼らは、他のシステムに依存するアプリケーションは、障害に対して回復力があるべきだと主張しています。
同じリンクで、理由が説明されています:
(たとえば)データベースの準備が整うのを待つという問題は、分散システムのはるかに大きな問題のほんの一部にすぎません。本番環境では、データベースがいつでも使用できなくなったり、ホストを移動したりする可能性があります。アプリケーションは、これらのタイプの障害に対して回復力を持つ必要があります。
これを処理するには、アプリケーションは、障害発生後にデータベースへの接続を再確立する必要があります。アプリケーションが接続を再試行すると、最終的にはデータベースに接続できるはずです。
基本的に、3つのオプションがあります。
healhcheck
でv2.1を使用します。例を見る ここ推奨される許容可能なソリューションは3)です。 Spring Retry は、 here のように使用できます。 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環境ファイル で定義できます。
複数のサービスを待つ必要がある場合は、 このプルリクエスト をマージし、必要なすべてのサービスを次のようなコマンドラインパラメータにリストできます。
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
特定の間隔なしで、設定サーバーが起動するまでアプリケーションの起動を遅らせます。