加粗样式微服务容器化如何实现顺序启动
前言:当我们有多个微服务部署到容器里时,就要涉及到谁先启动谁后启动问题,当然了你可以挨个手动启动,观察依次启动成功后再启动其他,你有这功夫,恐怕运维也不承认这么干,这里我们讨论的是如何实现容器编排顺序化。
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 你再做下面的启动,不然就循环请求它,直到服务启动成功)。
结尾:此记录自己的摸索过程,方便自己日后查找以及提供给需要帮助的人