docker-compose 发布spring cloud时的启动顺序问题解决方案

发布spring cloud时,会用docker compose去对服务进行编排,启动服务时,虽然有links或depends_on 的相关依赖关系,但是无法保证项目的启动顺序,因为无论是depends_on或是links在启动服务时并不会等待相关所依赖的服务完成,这就会出现一个问题,当服务注册eureka在启动中时,中心配置服务config已经启动了,并很有可能无法与eureka进行通信注册,业务服务也存在一样的困境,很有可能连数据库等相关配置都无法获取,因为没法保证业务服务在config启动完成以后才向其获取配置信息,如果是在多台机器上发布,比如服务注册与配置中心一台服务器,业务相关服务一台服务器,那么,这种机率可能会小点,因为可以人工控制启动顺序,今天讨论下如果只是单点发布,并存在相关依赖。

假如存在有以下服务编排,代码如下:

version: '3'
services:
  eureka-server:
    image: microservice/eureka-server
    build: platform-cloud-eureka
    restart : always
    ports:
      - "8080:8080"
    privileged: true
    networks:
      - miconet

  config-server:
    image: microservice/config-server
    build: platform-cloud-config
    volumes:
      - ./logs:/logs
    restart : always
    ports:
      - "8081:8081"
    links:
      - "eureka-server"
    privileged: true
    networks:
      - miconet

  system-server:
    image:  microservice/system-server
    build: platform-cloud-system-server
    volumes:
       - ./logs:/logs
    restart : always
    ports:
      - "8082:8082"
    links:
      - "eureka-server"
      - "config-server"
    privileged: true
    networks:
      - miconet

networks:
    miconet:

从代码上可以看出,服务的依赖关系比较明确。

依赖
依赖
依赖
system-server
config-server
eureka-server

如果直接按此服务编排进行发布,势必会造成服务启动后的注册失败或者无法获取配置文件,网上存在许多的解决方案,笔者也尝试过如健康检查,写shell脚本进行端口检查,但是不够严谨,容易出问题,最后看到网上一个处理此问题的插件,试用了一下,效果很好,记录一下。

推荐使用 Debian package.
话不多说,直接看使用方法,以下是对以上编排进行wait-for-it 的改造

version: '3'
services:
  eureka-server:
    image: microservice/eureka-server
    build: platform-cloud-eureka
    volumes:
      - /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime
    restart : always
    ports:
      - "8080:8080"
    privileged: true
    networks:
      - miconet

  config-server:
    image: microservice/config-server
    build: platform-cloud-config
    volumes:
      - ./logs:/logs
      - /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime
    restart : always
    ports:
      - "8081:8081"
    links:
      - "eureka-server"
    command: sh -c './wait-for-it.sh eureka-server:8080 -t 0  -- java -Djava.security.egd=file:/dev/./urandom -jar /app.jar'
    privileged: true
    networks:
      - miconet

 system-server:
    image:  microservice/system-server
    build: platform-cloud-system-server
    volumes:
       - ./logs:/logs
       - /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime
    restart : always
    ports:
      - "8082:8082"
    command: sh -c './wait-for-it.sh config-server:8081 -t 0  -- java -Djava.security.egd=file:/dev/./urandom -jar /app.jar'
    privileged: true
    networks:
      - miconet

networks:
    miconet:

wait for it的用法,官方有相关说明,此处用的-t 0 是不做timeout限制,其它参数可以灵活配置
Usage:
$WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args]
-h HOST | --host=HOST Host or IP under test
-p PORT | --port=PORT TCP port under test
Alternatively, you specify the host and port as host:port
-s | --strict Only execute subcommand if the test succeeds
-q | --quiet Don’t output any status messages
-t TIMEOUT | --timeout=TIMEOUT
Timeout in seconds, zero for no timeout
– COMMAND ARGS Execute command with args after the test finishes

下面展示一下用到的 Dockerfile 示例,上面几个实例大体相同:

FROM java:8
VOLUME /tmp
ADD  system-server-1.0-SNAPSHOT.jar app.jar
ADD wait-for-it.sh /wait-for-it.sh
RUN sh -c 'touch /app.jar'
RUN sh -c 'chmod 777 /wait-for-it.sh'
#EXPOSE 8082
#EXPOSE 28000
#ENTRYPOINT java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -Duser.timezone=Asia/Shanghai -Dfile.encoding=UTF-8  -jar /opt/app.jar

相关的包结构如下
在这里插入图片描述
假如在eureka没有完成启动时,config-server会等待eureka启动完成后再进行启动操作,达到了按顺序启动的目的:
在这里插入图片描述

你可能感兴趣的:(spring,cloud)