加粗样式微服务容器化如何实现顺序启动

前言:当我们有多个微服务部署到容器里时,就要涉及到谁先启动谁后启动问题,当然了你可以挨个手动启动,观察依次启动成功后再启动其他,你有这功夫,恐怕运维也不承认这么干,这里我们讨论的是如何实现容器编排顺序化。

1、这里我使用docker-compose编排,下面我贴出部分的代码:

#docker compose编排微服务脚本
version: "3"
services:
  #服务注册与发现中心1
  eureka-server1:
    image: eureka-server:1.0
    hostname: eureka-server1
    container_name: eureka-server1
    restart: always
    network_mode: "bridge"
    ports:
      - "17801:17801"
    volumes:
      - ${log_path}:/app/log
    environment:
      - jarName=eureka-server-1.0.jar
    expose:
      - 17801
    extra_hosts:
      - "eureka-server1:${eureka_server1}"
      - "eureka-server2:${eureka_server2}"
    entrypoint: /app/checkServiceStart.sh -c 'java -Dspring.profiles.active=eureka-server1 -jar eureka-server-1.0.jar --server.port=17801'

  #服务注册与发现中心2
  eureka-server2:
    image: eureka-server:1.0
    hostname: eureka-server2
    container_name: eureka-server2
    restart: always
    network_mode: "bridge"
    ports:
      - "17802:17802"
    depends_on:
      - eureka-server1
    volumes:
      - ${log_path}:/app/log
    environment:
      - jarName=eureka-server-1.0.jar
    expose:
      - 17802
    extra_hosts:
      - "eureka-server1:${eureka_server1}"
      - "eureka-server2:${eureka_server2}"
    entrypoint: /app/checkServiceStart.sh -d ${eureka_server1}:17801 -c 'java -Dspring.profiles.active=eureka-server2 -jar eureka-server-1.0.jar --server.port=17802';

  #配置中心
  config-server:
    image: config-server:1.0
    hostname: config-server
    container_name: config-server
    restart: always
    network_mode: "bridge"
    ports:
      - "17822:17822"
    depends_on:
      - eureka-server1
      - eureka-server2
    volumes:
      - ${log_path}:/app/log
    environment:
      - jarName=config-server-1.0.jar
    expose:
      - 17822
    extra_hosts:
      - "eureka-server1:${eureka_server1}"
      - "eureka-server2:${eureka_server2}"
    entrypoint: /app/checkServiceStart.sh -d ${eureka_server1}:17801,${eureka_server2}:17802 -c 'java -Dspring.profiles.active=${config_server_env} -jar config-server-1.0.jar --server.port=17822';

这里显然我们得知,先要启动eureka-server1,然后再启动eureka-server2, 然后再启动config-server.
这里关键是checkServiceStart.sh 脚本里实现顺序启动,下面请看这个脚本的内容:

#!/bin/bash
#set -x
#******************************************************************************
#检测服务是否启动的脚本
#******************************************************************************
: ${SLEEP_SECOND:=10}
wait_for(){
    echo Waiting for $1 to listen on $2...
    responseCode=$(curl -sL -w "%{http_code}\n" http://$1:$2/actuator/health -o /dev/null)
    echo $responseCode
    while [ $responseCode -ne 200 ]
     do
        echo waiting for service $1:$2 start up ...
        sleep $SLEEP_SECOND
        responseCode=$(curl -sL -w "%{http_code}\n" http://$1:$2/actuator/health -o /dev/null)
     done
}
declare DEPENDS
declare CMD
while getopts "d:c:" arg
do
    case $arg in
        d)
            DEPENDS=$OPTARG
            ;;
        c)
            CMD=$OPTARG
            ;;
        ?)
            echo "unknown argument"
            exit 1
            ;;
    esac
done

for var in ${DEPENDS//,/ } #${DEPENDS//,/ }把DEPENDS中的,替换为空格
do
    host=${var%:*} # 删掉最后一个  :  及其右边的字符串
    port=${var#*:} # 删掉第一个 : 及其左边的字符串
    wait_for $host $port
done
eval $CMD #eval命令相当于把$CMD中的命令执行一次
#避免执行完命令之后退出容器
tail -f /dev/null

这里主要使用curl命令去循环检测微服务中的健康检查url(actuator/health),通过响应进行判断服务是否真正启动成功,网上有说使用nc命令进行判断,这里说下使用这个命令不能实现真正意义上的顺序启动(因为这个命令只要进程起来就算成功(服务可能还未完全起来),微服务可能先都能启动,后面去寻找配置依赖时候,可能启动没那么快,就造成进程退出的,我建议你是要curl 检测微服务的健康请求,返回200 你再做下面的启动,不然就循环请求它,直到服务启动成功)。

结尾:此记录自己的摸索过程,方便自己日后查找以及提供给需要帮助的人