要实现无感部署,即在更新应用程序时不影响用户访问接口,可以考虑使用以下方法:
1、使用负载均衡器:在部署应用程序时,通过负载均衡器将流量分发到多个实例上。这样,当更新一个实例时,其他实例仍然可以继续提供服务,从而保证用户访问接口的稳定性。
2、Blue-Green 部署:使用Blue-Green 部署策略,即同时部署两个版本的应用程序,一个作为主要版本(Blue),一个作为备用版本(Green)。当需要更新应用程序时,先将新版本部署为备用版本,然后逐渐将流量切换到新版本,最终将旧版本下线。这样可以保证用户在更新过程中不受影响。
3、Canary 部署:使用Canary 部署策略,即逐步将新版本应用程序部署到生产环境中的一小部分节点,然后逐渐扩大部署范围。这样可以在更新过程中逐步验证新版本的稳定性,避免一次性影响所有用户。
通过以上方法,您可以实现无感部署,确保在更新应用程序时不影响用户访问接口。同时,建议在部署过程中进行充分的测试和监控,以确保更新过程的稳定性和可用性。
环境
- 服务器:CentOS 7.9.2009
- docker-compose版本:3.9
- docker版本:20.10.12
- 根目录在/docker/mes
docker-compose.yml
version: "3.9"
services:
fcat-mes-main-blue:
image: adoptopenjdk/openjdk8-openj9:alpine-slim
container_name: fcat-mes-main-blue
restart: always
ports:
- "16219:11001"
volumes:
- ./fcat-mes-main-blue/app:/app
- /etc/localtime:/etc/localtime
environment:
- TZ=Asia/Shanghai
command: [
'java',
'-Xmx600m',
'-jar',
'/app/fcat-mes-main.jar'
]
deploy:
resources:
limits:
memory: 800M
fcat-mes-main-green:
image: adoptopenjdk/openjdk8-openj9:alpine-slim
container_name: fcat-mes-main-green
restart: always
ports:
- "16220:11001"
volumes:
- ./fcat-mes-main-green/app:/app
- /etc/localtime:/etc/localtime
environment:
- TZ=Asia/Shanghai
command: [
'java',
'-Xmx600m',
'-jar',
'/app/fcat-mes-main.jar'
]
deploy:
resources:
limits:
memory: 800M
fcat-nginx:
image: nginx:1.21.0
container_name: fcat-nginx
restart: always
privileged: true
environment:
- TZ=Asia/Shanghai
ports:
- 16221:16221
volumes:
- /etc/localtime:/etc/localtime
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/log:/var/log/nginx
- ./nginx/web:/web
- ./logs:/logs
deploy:
resources:
limits:
memory: 1024M
version: "3.9"
services:
fcat-mes-main-blue:
image: adoptopenjdk/openjdk8-openj9:alpine-slim
container_name: fcat-mes-main-blue
restart: always
ports:
- "16219:11001"
volumes:
- ./fcat-mes-main-blue/app:/app
- /etc/localtime:/etc/localtime
environment:
- TZ=Asia/Shanghai
command: [
'java',
'-Xmx600m',
'-jar',
'/app/fcat-mes-main.jar'
]
deploy:
resources:
limits:
memory: 800M
fcat-mes-main-green:
image: adoptopenjdk/openjdk8-openj9:alpine-slim
container_name: fcat-mes-main-green
restart: always
ports:
- "16220:11001"
volumes:
- ./fcat-mes-main-green/app:/app
- /etc/localtime:/etc/localtime
environment:
- TZ=Asia/Shanghai
command: [
'java',
'-Xmx600m',
'-jar',
'/app/fcat-mes-main.jar'
]
deploy:
resources:
limits:
memory: 800M
fcat-nginx:
image: nginx:1.21.0
container_name: fcat-nginx
restart: always
privileged: true
environment:
- TZ=Asia/Shanghai
ports:
- 16221:16221
volumes:
- /etc/localtime:/etc/localtime
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/log:/var/log/nginx
- ./nginx/web:/web
- ./logs:/logs
deploy:
resources:
limits:
memory: 1024M
nginx/conf.d/main.conf
server {
listen 16221;
listen [::]:16221;
charset utf-8,gbk;
client_max_body_size 10m; # 设置最大上传文件大小为10MB
location /dev-api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://mes_main_service/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
upstream mes_main_service{
server fcat-mes-main-blue:11001;
server fcat-mes-main-green:11001 weight=100;
}
server {
listen 16221;
listen [::]:16221;
charset utf-8,gbk;
client_max_body_size 10m; # 设置最大上传文件大小为10MB
location /dev-api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://mes_main_service/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
upstream mes_main_service{
server fcat-mes-main-blue:11001;
server fcat-mes-main-green:11001 weight=100;
}
nginx/conf.d/blue.conf_bak
server {
listen 16221;
listen [::]:16221;
charset utf-8,gbk;
client_max_body_size 10m; # 设置最大上传文件大小为10MB
location /dev-api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://mes_main_service/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
upstream mes_main_service{
server fcat-mes-main-blue:11001 weight=100;
server fcat-mes-main-green:11001 ;
}
server {
listen 16221;
listen [::]:16221;
charset utf-8,gbk;
client_max_body_size 10m; # 设置最大上传文件大小为10MB
location /dev-api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://mes_main_service/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
upstream mes_main_service{
server fcat-mes-main-blue:11001 weight=100;
server fcat-mes-main-green:11001 ;
}
nginx/conf.d/green.conf_bak
server {
listen 16221;
listen [::]:16221;
charset utf-8,gbk;
client_max_body_size 10m; # 设置最大上传文件大小为10MB
location /dev-api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://mes_main_service/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
upstream mes_main_service{
server fcat-mes-main-blue:11001;
server fcat-mes-main-green:11001 weight=100;
}
server {
listen 16221;
listen [::]:16221;
charset utf-8,gbk;
client_max_body_size 10m; # 设置最大上传文件大小为10MB
location /dev-api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://mes_main_service/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
upstream mes_main_service{
server fcat-mes-main-blue:11001;
server fcat-mes-main-green:11001 weight=100;
}
运行服务
shell
docker-compose up -d
docker-compose up -d
curl http://192.168.9.126:16219/test/version
{
"version": "v1"
}
curl http://192.168.9.126:16220/test/version
{
"version": "v2"
}
curl http://192.168.9.126:16221/dev-api/test/version
{
"version": "v2"
}
curl http://192.168.9.126:16219/test/version
{
"version": "v1"
}
curl http://192.168.9.126:16220/test/version
{
"version": "v2"
}
curl http://192.168.9.126:16221/dev-api/test/version
{
"version": "v2"
}
bluegreen.txt
green
green
deploy.sh
#!/bin/bash
# 记录当前使用蓝色版本还是绿色版本
filename="bluegreen.txt"
# 读取当前使用版本
content=$(cat "$filename")
# 蓝色版本
blue_app_name="fcat-mes-main-blue"
# 绿色版本
green_app_name="fcat-mes-main-green"
# jar应用名称
jar_name="fcat-mes-main"
# 指定要匹配的字符串
search_string="Application Start Success"
echo "当前部署版本:$content"
case $content in
"blue")
rm -rf nginx/conf.d/main.conf
cp nginx/conf.d/green.conf_bak nginx/conf.d/main.conf
rm -rf $green_app_name/app/$jar_name.jar_bak
cp $green_app_name/app/$jar_name.jar $green_app_name/app/$jar_name.jar_bak
rm -rf $green_app_name/app/$jar_name.jar
cp $jar_name.jar $green_app_name/app/
echo "" > output.log
docker-compose restart $green_app_name
timeout 60 docker-compose logs -f --tail=0 $green_app_name | while IFS= read -r line; do
echo "$line"
if echo "$line" | grep -q "$search_string"; then
pkill -P $$ # 杀死timeout进程
break
fi
done > output.log 2>&1
if grep -q "$search_string" output.log; then
echo "$search_string"
docker-compose exec fcat-nginx nginx -s reload
echo "green" > bluegreen.txt
else
echo "Error detected in logs. Rolling back..."
# 在这里编写回滚操作的代码
rm -rf nginx/conf.d/main.conf
cp nginx/conf.d/blue.conf_bak nginx/conf.d/main.conf
rm -rf $green_app_name/app/$jar_name.jar
cp $green_app_name/app/$jar_name.jar_bak $green_app_name/app/$jar_name.jar
docker-compose restart $green_app_name
fi
;;
"green")
rm -rf nginx/conf.d/main.conf
cp nginx/conf.d/blue.conf_bak nginx/conf.d/main.conf
rm -rf $blue_app_name/app/$jar_name.jar_bak
cp $blue_app_name/app/$jar_name.jar $blue_app_name/app/$jar_name.jar_bak
rm -rf $blue_app_name/app/$jar_name.jar
cp $jar_name.jar $blue_app_name/app/
echo "" > output.log
docker-compose restart $blue_app_name
timeout 60 docker-compose logs -f --tail=0 $blue_app_name | while IFS= read -r line; do
echo "$line"
if echo "$line" | grep -q "$search_string"; then
echo "Found the search string. Exiting..."
pkill -P $$ # 杀死timeout进程
break
fi
done > output.log 2>&1
if grep -q "$search_string" output.log; then
echo "$search_string"
docker-compose exec fcat-nginx nginx -s reload
echo "blue" > bluegreen.txt
else
echo "Error detected in logs. Rolling back..."
# 在这里编写回滚操作的代码
rm -rf nginx/conf.d/main.conf
cp nginx/conf.d/green.conf_bak nginx/conf.d/main.conf
rm -rf $blue_app_name/app/$jar_name.jar
cp $blue_app_name/app/$jar_name.jar_bak $blue_app_name/app/$jar_name.jar
docker-compose restart $blue_app_name
fi
;;
"*")
echo "bluegreen.txt 内容不对"
;;
esac
#!/bin/bash
# 记录当前使用蓝色版本还是绿色版本
filename="bluegreen.txt"
# 读取当前使用版本
content=$(cat "$filename")
# 蓝色版本
blue_app_name="fcat-mes-main-blue"
# 绿色版本
green_app_name="fcat-mes-main-green"
# jar应用名称
jar_name="fcat-mes-main"
# 指定要匹配的字符串
search_string="Application Start Success"
echo "当前部署版本:$content"
case $content in
"blue")
rm -rf nginx/conf.d/main.conf
cp nginx/conf.d/green.conf_bak nginx/conf.d/main.conf
rm -rf $green_app_name/app/$jar_name.jar_bak
cp $green_app_name/app/$jar_name.jar $green_app_name/app/$jar_name.jar_bak
rm -rf $green_app_name/app/$jar_name.jar
cp $jar_name.jar $green_app_name/app/
echo "" > output.log
docker-compose restart $green_app_name
timeout 60 docker-compose logs -f --tail=0 $green_app_name | while IFS= read -r line; do
echo "$line"
if echo "$line" | grep -q "$search_string"; then
pkill -P $$ # 杀死timeout进程
break
fi
done > output.log 2>&1
if grep -q "$search_string" output.log; then
echo "$search_string"
docker-compose exec fcat-nginx nginx -s reload
echo "green" > bluegreen.txt
else
echo "Error detected in logs. Rolling back..."
# 在这里编写回滚操作的代码
rm -rf nginx/conf.d/main.conf
cp nginx/conf.d/blue.conf_bak nginx/conf.d/main.conf
rm -rf $green_app_name/app/$jar_name.jar
cp $green_app_name/app/$jar_name.jar_bak $green_app_name/app/$jar_name.jar
docker-compose restart $green_app_name
fi
;;
"green")
rm -rf nginx/conf.d/main.conf
cp nginx/conf.d/blue.conf_bak nginx/conf.d/main.conf
rm -rf $blue_app_name/app/$jar_name.jar_bak
cp $blue_app_name/app/$jar_name.jar $blue_app_name/app/$jar_name.jar_bak
rm -rf $blue_app_name/app/$jar_name.jar
cp $jar_name.jar $blue_app_name/app/
echo "" > output.log
docker-compose restart $blue_app_name
timeout 60 docker-compose logs -f --tail=0 $blue_app_name | while IFS= read -r line; do
echo "$line"
if echo "$line" | grep -q "$search_string"; then
echo "Found the search string. Exiting..."
pkill -P $$ # 杀死timeout进程
break
fi
done > output.log 2>&1
if grep -q "$search_string" output.log; then
echo "$search_string"
docker-compose exec fcat-nginx nginx -s reload
echo "blue" > bluegreen.txt
else
echo "Error detected in logs. Rolling back..."
# 在这里编写回滚操作的代码
rm -rf nginx/conf.d/main.conf
cp nginx/conf.d/green.conf_bak nginx/conf.d/main.conf
rm -rf $blue_app_name/app/$jar_name.jar
cp $blue_app_name/app/$jar_name.jar_bak $blue_app_name/app/$jar_name.jar
docker-compose restart $blue_app_name
fi
;;
"*")
echo "bluegreen.txt 内容不对"
;;
esac
deploy-ifms.sh
shell
#!/bin/bash
cd /docker/mes/
# 记录当前使用蓝色版本还是绿色版本
filename="ifms-bluegreen.txt"
# 读取当前使用版本
content=$(cat "$filename")
# 蓝色版本
blue_app_name="ifms-admin-blue"
# 绿色版本
green_app_name="ifms-admin-green"
# jar应用名称
jar_name="ifms-admin"
# 指定要匹配的字符串
search_string="Application Start Success"
error_string="Application Start Failed"
# 抓取的日志记录文件
log_file="ifms-output.log"
# nginx配置文件,不需要.conf后缀
nginx_file="mes"
wait_minutes=120
# 公司的ID
companyId=1
echo "当前部署版本:$content"
# 参数:json_data='{"companyId": "11", "status": "1", "msg": "中文哈哈"}'
send_mail(){
local json_data=$1
echo "$json_data"
# HTTP 接口地址和参数
url="http://www.tsuantone.top:16020/system/mail/deploy1"
# 发送 POST 请求,指定 Content-Type 为 application/json
response=$(curl -s -X POST -H "Content-Type: application/json" -d "$json_data" "$url")
# 输出响应结果
echo "Response: $response"
}
escape_string() {
local string="$1"
escaped_string=$(echo "$string" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\n/\\n/g; s/\t/\\t/g')
echo "$escaped_string"
}
case $content in
"blue")
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-green.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $green_app_name/app/$jar_name.jar_bak
cp $green_app_name/app/$jar_name.jar $green_app_name/app/$jar_name.jar_bak
rm -rf $green_app_name/app/$jar_name.jar
cp $jar_name.jar $green_app_name/app/
echo "" > $log_file
cd /docker/mes/
docker-compose restart $green_app_name
timeout $wait_minutes docker-compose logs -f --tail=0 $green_app_name | while IFS= read -r line; do
echo "$line"
if echo "$line" | grep -q "$search_string"; then
pkill -P $$ # 杀死timeout进程
break
fi
done > $log_file 2>&1
content_log=$(cat $log_file)
# 去掉shell终端的颜色显示
content_log=$(echo "$content_log" | sed -r "s/\x1B\[[0-9;]*[mGK]//g")
#content_log=$(escape_string "$original_string")
echo "$content_log"
if grep -q "$search_string" $log_file; then
echo "$search_string"
json_data=$(jq -n --arg company_id "$companyId" --arg status "1" --arg msg "$content_log" '{companyId: $company_id, status: $status, msg: $msg}')
send_mail "$json_data"
cd /docker/mes/
docker-compose restart fcat-nginx
echo "green" > $filename
else
echo "$error_string"
json_data=$(jq -n --arg company_id "$companyId" --arg status "0" --arg msg "$content_log" '{companyId: $company_id, status: $status, msg: $msg}')
send_mail "$json_data"
# 在这里编写回滚操作的代码
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-blue.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $green_app_name/app/$jar_name.jar
cp $green_app_name/app/$jar_name.jar_bak $green_app_name/app/$jar_name.jar
docker-compose restart $green_app_name
fi
;;
"green")
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-blue.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $blue_app_name/app/$jar_name.jar_bak
cp $blue_app_name/app/$jar_name.jar $blue_app_name/app/$jar_name.jar_bak
rm -rf $blue_app_name/app/$jar_name.jar
cp $jar_name.jar $blue_app_name/app/
echo "" > $log_file
docker-compose restart $blue_app_name
timeout $wait_minutes docker-compose logs -f --tail=0 $blue_app_name | while IFS= read -r line; do
echo "$line"
if echo "$line" | grep -q "$search_string"; then
pkill -P $$ # 杀死timeout进程
break
fi
done > $log_file 2>&1
content_log=$(cat $log_file)
# 去掉shell终端的颜色显示
content_log=$(echo "$content_log" | sed -r "s/\x1B\[[0-9;]*[mGK]//g")
#content_log=$(escape_string "$original_string")
echo "$content_log"
if grep -q "$search_string" $log_file; then
echo "$search_string"
json_data=$(jq -n --arg company_id "$companyId" --arg status "1" --arg msg "$content_log" '{companyId: $company_id, status: $status, msg: $msg}')
send_mail "$json_data"
cd /docker/mes/
docker-compose restart fcat-nginx
echo "blue" > $filename
else
echo "$error_string"
json_data=$(jq -n --arg company_id "$companyId" --arg status "0" --arg msg "$content_log" '{companyId: $company_id, status: $status, msg: $msg}')
send_mail "$json_data"
# 在这里编写回滚操作的代码
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-green.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $blue_app_name/app/$jar_name.jar
cp $blue_app_name/app/$jar_name.jar_bak $blue_app_name/app/$jar_name.jar
docker-compose restart $blue_app_name
fi
;;
"*")
echo "bluegreen.txt 内容不对"
;;
esac
#!/bin/bash
cd /docker/mes/
# 记录当前使用蓝色版本还是绿色版本
filename="ifms-bluegreen.txt"
# 读取当前使用版本
content=$(cat "$filename")
# 蓝色版本
blue_app_name="ifms-admin-blue"
# 绿色版本
green_app_name="ifms-admin-green"
# jar应用名称
jar_name="ifms-admin"
# 指定要匹配的字符串
search_string="Application Start Success"
error_string="Application Start Failed"
# 抓取的日志记录文件
log_file="ifms-output.log"
# nginx配置文件,不需要.conf后缀
nginx_file="mes"
wait_minutes=120
# 公司的ID
companyId=1
echo "当前部署版本:$content"
# 参数:json_data='{"companyId": "11", "status": "1", "msg": "中文哈哈"}'
send_mail(){
local json_data=$1
echo "$json_data"
# HTTP 接口地址和参数
url="http://www.tsuantone.top:16020/system/mail/deploy1"
# 发送 POST 请求,指定 Content-Type 为 application/json
response=$(curl -s -X POST -H "Content-Type: application/json" -d "$json_data" "$url")
# 输出响应结果
echo "Response: $response"
}
escape_string() {
local string="$1"
escaped_string=$(echo "$string" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\n/\\n/g; s/\t/\\t/g')
echo "$escaped_string"
}
case $content in
"blue")
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-green.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $green_app_name/app/$jar_name.jar_bak
cp $green_app_name/app/$jar_name.jar $green_app_name/app/$jar_name.jar_bak
rm -rf $green_app_name/app/$jar_name.jar
cp $jar_name.jar $green_app_name/app/
echo "" > $log_file
cd /docker/mes/
docker-compose restart $green_app_name
timeout $wait_minutes docker-compose logs -f --tail=0 $green_app_name | while IFS= read -r line; do
echo "$line"
if echo "$line" | grep -q "$search_string"; then
pkill -P $$ # 杀死timeout进程
break
fi
done > $log_file 2>&1
content_log=$(cat $log_file)
# 去掉shell终端的颜色显示
content_log=$(echo "$content_log" | sed -r "s/\x1B\[[0-9;]*[mGK]//g")
#content_log=$(escape_string "$original_string")
echo "$content_log"
if grep -q "$search_string" $log_file; then
echo "$search_string"
json_data=$(jq -n --arg company_id "$companyId" --arg status "1" --arg msg "$content_log" '{companyId: $company_id, status: $status, msg: $msg}')
send_mail "$json_data"
cd /docker/mes/
docker-compose restart fcat-nginx
echo "green" > $filename
else
echo "$error_string"
json_data=$(jq -n --arg company_id "$companyId" --arg status "0" --arg msg "$content_log" '{companyId: $company_id, status: $status, msg: $msg}')
send_mail "$json_data"
# 在这里编写回滚操作的代码
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-blue.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $green_app_name/app/$jar_name.jar
cp $green_app_name/app/$jar_name.jar_bak $green_app_name/app/$jar_name.jar
docker-compose restart $green_app_name
fi
;;
"green")
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-blue.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $blue_app_name/app/$jar_name.jar_bak
cp $blue_app_name/app/$jar_name.jar $blue_app_name/app/$jar_name.jar_bak
rm -rf $blue_app_name/app/$jar_name.jar
cp $jar_name.jar $blue_app_name/app/
echo "" > $log_file
docker-compose restart $blue_app_name
timeout $wait_minutes docker-compose logs -f --tail=0 $blue_app_name | while IFS= read -r line; do
echo "$line"
if echo "$line" | grep -q "$search_string"; then
pkill -P $$ # 杀死timeout进程
break
fi
done > $log_file 2>&1
content_log=$(cat $log_file)
# 去掉shell终端的颜色显示
content_log=$(echo "$content_log" | sed -r "s/\x1B\[[0-9;]*[mGK]//g")
#content_log=$(escape_string "$original_string")
echo "$content_log"
if grep -q "$search_string" $log_file; then
echo "$search_string"
json_data=$(jq -n --arg company_id "$companyId" --arg status "1" --arg msg "$content_log" '{companyId: $company_id, status: $status, msg: $msg}')
send_mail "$json_data"
cd /docker/mes/
docker-compose restart fcat-nginx
echo "blue" > $filename
else
echo "$error_string"
json_data=$(jq -n --arg company_id "$companyId" --arg status "0" --arg msg "$content_log" '{companyId: $company_id, status: $status, msg: $msg}')
send_mail "$json_data"
# 在这里编写回滚操作的代码
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-green.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $blue_app_name/app/$jar_name.jar
cp $blue_app_name/app/$jar_name.jar_bak $blue_app_name/app/$jar_name.jar
docker-compose restart $blue_app_name
fi
;;
"*")
echo "bluegreen.txt 内容不对"
;;
esac
deploy-fcat.sh
shell
#!/bin/bash
# 记录当前使用蓝色版本还是绿色版本
filename="ruoyi-admin-bluegreen.txt"
# 读取当前使用版本
content=$(cat "$filename")
# 蓝色版本
blue_app_name="ruoyi-admin-blue"
# 绿色版本
green_app_name="ruoyi-admin-green"
# jar应用名称
jar_name="ruoyi-admin"
jar_path="/root/ruoyi-vue/ruoyi-admin/target/"
# 指定要匹配的字符串
search_string="Application Start Success"
error_string="Application Start Failed"
# 抓取的日志记录文件
log_file="ruoyi-admin-output.log"
# nginx配置文件,不需要.conf后缀
nginx_file="ruoyi"
# 检测启动日志等待时间
wait_minutes=120
# 切换nginx的蓝绿版本,需要留时间处理请求中的接口返回
wait_inteface_deal_minutes=30
# 名称
name="FCAT"
echo "当前部署版本:$content"
# 参数:json_data='{"name": "FCAT", "status": "1", "msg": "中文哈哈"}'
send_mail(){
local json_data=$1
echo "$json_data"
# HTTP 接口地址和参数
url="https://localhost/prod-api/system/mail/deploy"
# 发送 POST 请求,指定 Content-Type 为 application/json
response=$(curl -s -X POST -H "Content-Type: application/json" -d "$json_data" -k "$url")
# 输出响应结果
echo "Response: $response"
}
escape_string() {
local string="$1"
escaped_string=$(echo "$string" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\n/\\n/g; s/\t/\\t/g')
echo "$escaped_string"
}
case $content in
"blue")
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-green.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $green_app_name/jar/$jar_name.jar_bak
cp $green_app_name/jar/$jar_name.jar $green_app_name/jar/$jar_name.jar_bak
rm -rf $green_app_name/jar/$jar_name.jar
cp $jar_path$jar_name.jar $green_app_name/jar/
echo "" > $log_file
docker-compose restart $green_app_name
timeout $wait_minutes docker-compose logs -f --tail=0 $green_app_name | while IFS= read -r line; do
echo "$line"
if echo "$line" | grep -q "$search_string"; then
pkill -P $$ # 杀死timeout进程
break
fi
done > $log_file 2>&1
content_log=$(cat $log_file)
# 去掉shell终端的颜色显示
content_log=$(echo "$content_log" | sed -r "s/\x1B\[[0-9;]*[mGK]//g")
#content_log=$(escape_string "$original_string")
echo "$content_log"
if grep -q "$search_string" $log_file; then
echo "$search_string"
docker-compose exec fcat-nginx nginx -s reload
sleep $wait_inteface_deal_minutes
json_data=$(jq -n --arg name "$name" --arg status "1" --arg msg "$content_log" '{name: $name, status: $status, msg: $msg}')
send_mail "$json_data"
echo "green" > $filename
docker-compose stop $blue_app_name
else
echo "$error_string"
json_data=$(jq -n --arg name "$name" --arg status "0" --arg msg "$content_log" '{name: $name, status: $status, msg: $msg}')
send_mail "$json_data"
# 在这里编写回滚操作的代码
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-blue.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $green_app_name/jar/$jar_name.jar
cp $green_app_name/jar/$jar_name.jar_bak $green_app_name/jar/$jar_name.jar
docker-compose restart $green_app_name
fi
;;
"green")
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-blue.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $blue_app_name/jar/$jar_name.jar_bak
cp $blue_app_name/jar/$jar_name.jar $blue_app_name/jar/$jar_name.jar_bak
rm -rf $blue_app_name/jar/$jar_name.jar
cp $jar_path$jar_name.jar $blue_app_name/jar/
echo "" > $log_file
docker-compose restart $blue_app_name
timeout $wait_minutes docker-compose logs -f --tail=0 $blue_app_name | while IFS= read -r line; do
echo "$line"
if echo "$line" | grep -q "$search_string"; then
pkill -P $$ # 杀死timeout进程
break
fi
done > $log_file 2>&1
content_log=$(cat $log_file)
# 去掉shell终端的颜色显示
content_log=$(echo "$content_log" | sed -r "s/\x1B\[[0-9;]*[mGK]//g")
#content_log=$(escape_string "$original_string")
echo "$content_log"
if grep -q "$search_string" $log_file; then
echo "$search_string"
docker-compose exec fcat-nginx nginx -s reload
sleep $wait_inteface_deal_minutes
json_data=$(jq -n --arg name "$name" --arg status "1" --arg msg "$content_log" '{name: $name, status: $status, msg: $msg}')
send_mail "$json_data"
echo "blue" > $filename
docker-compose stop $green_app_name
else
echo "$error_string"
json_data=$(jq -n --arg name "$name" --arg status "0" --arg msg "$content_log" '{name: $name, status: $status, msg: $msg}')
send_mail "$json_data"
# 在这里编写回滚操作的代码
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-green.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $blue_app_name/jar/$jar_name.jar
cp $blue_app_name/jar/$jar_name.jar_bak $blue_app_name/jar/$jar_name.jar
docker-compose restart $blue_app_name
fi
;;
"*")
echo "$filename内容不对"
;;
esac
#!/bin/bash
# 记录当前使用蓝色版本还是绿色版本
filename="ruoyi-admin-bluegreen.txt"
# 读取当前使用版本
content=$(cat "$filename")
# 蓝色版本
blue_app_name="ruoyi-admin-blue"
# 绿色版本
green_app_name="ruoyi-admin-green"
# jar应用名称
jar_name="ruoyi-admin"
jar_path="/root/ruoyi-vue/ruoyi-admin/target/"
# 指定要匹配的字符串
search_string="Application Start Success"
error_string="Application Start Failed"
# 抓取的日志记录文件
log_file="ruoyi-admin-output.log"
# nginx配置文件,不需要.conf后缀
nginx_file="ruoyi"
# 检测启动日志等待时间
wait_minutes=120
# 切换nginx的蓝绿版本,需要留时间处理请求中的接口返回
wait_inteface_deal_minutes=30
# 名称
name="FCAT"
echo "当前部署版本:$content"
# 参数:json_data='{"name": "FCAT", "status": "1", "msg": "中文哈哈"}'
send_mail(){
local json_data=$1
echo "$json_data"
# HTTP 接口地址和参数
url="https://localhost/prod-api/system/mail/deploy"
# 发送 POST 请求,指定 Content-Type 为 application/json
response=$(curl -s -X POST -H "Content-Type: application/json" -d "$json_data" -k "$url")
# 输出响应结果
echo "Response: $response"
}
escape_string() {
local string="$1"
escaped_string=$(echo "$string" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\n/\\n/g; s/\t/\\t/g')
echo "$escaped_string"
}
case $content in
"blue")
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-green.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $green_app_name/jar/$jar_name.jar_bak
cp $green_app_name/jar/$jar_name.jar $green_app_name/jar/$jar_name.jar_bak
rm -rf $green_app_name/jar/$jar_name.jar
cp $jar_path$jar_name.jar $green_app_name/jar/
echo "" > $log_file
docker-compose restart $green_app_name
timeout $wait_minutes docker-compose logs -f --tail=0 $green_app_name | while IFS= read -r line; do
echo "$line"
if echo "$line" | grep -q "$search_string"; then
pkill -P $$ # 杀死timeout进程
break
fi
done > $log_file 2>&1
content_log=$(cat $log_file)
# 去掉shell终端的颜色显示
content_log=$(echo "$content_log" | sed -r "s/\x1B\[[0-9;]*[mGK]//g")
#content_log=$(escape_string "$original_string")
echo "$content_log"
if grep -q "$search_string" $log_file; then
echo "$search_string"
docker-compose exec fcat-nginx nginx -s reload
sleep $wait_inteface_deal_minutes
json_data=$(jq -n --arg name "$name" --arg status "1" --arg msg "$content_log" '{name: $name, status: $status, msg: $msg}')
send_mail "$json_data"
echo "green" > $filename
docker-compose stop $blue_app_name
else
echo "$error_string"
json_data=$(jq -n --arg name "$name" --arg status "0" --arg msg "$content_log" '{name: $name, status: $status, msg: $msg}')
send_mail "$json_data"
# 在这里编写回滚操作的代码
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-blue.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $green_app_name/jar/$jar_name.jar
cp $green_app_name/jar/$jar_name.jar_bak $green_app_name/jar/$jar_name.jar
docker-compose restart $green_app_name
fi
;;
"green")
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-blue.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $blue_app_name/jar/$jar_name.jar_bak
cp $blue_app_name/jar/$jar_name.jar $blue_app_name/jar/$jar_name.jar_bak
rm -rf $blue_app_name/jar/$jar_name.jar
cp $jar_path$jar_name.jar $blue_app_name/jar/
echo "" > $log_file
docker-compose restart $blue_app_name
timeout $wait_minutes docker-compose logs -f --tail=0 $blue_app_name | while IFS= read -r line; do
echo "$line"
if echo "$line" | grep -q "$search_string"; then
pkill -P $$ # 杀死timeout进程
break
fi
done > $log_file 2>&1
content_log=$(cat $log_file)
# 去掉shell终端的颜色显示
content_log=$(echo "$content_log" | sed -r "s/\x1B\[[0-9;]*[mGK]//g")
#content_log=$(escape_string "$original_string")
echo "$content_log"
if grep -q "$search_string" $log_file; then
echo "$search_string"
docker-compose exec fcat-nginx nginx -s reload
sleep $wait_inteface_deal_minutes
json_data=$(jq -n --arg name "$name" --arg status "1" --arg msg "$content_log" '{name: $name, status: $status, msg: $msg}')
send_mail "$json_data"
echo "blue" > $filename
docker-compose stop $green_app_name
else
echo "$error_string"
json_data=$(jq -n --arg name "$name" --arg status "0" --arg msg "$content_log" '{name: $name, status: $status, msg: $msg}')
send_mail "$json_data"
# 在这里编写回滚操作的代码
rm -rf nginx/conf.d/$nginx_file.conf
cp nginx/conf.d/$nginx_file-green.conf_bak nginx/conf.d/$nginx_file.conf
rm -rf $blue_app_name/jar/$jar_name.jar
cp $blue_app_name/jar/$jar_name.jar_bak $blue_app_name/jar/$jar_name.jar
docker-compose restart $blue_app_name
fi
;;
"*")
echo "$filename内容不对"
;;
esac
上传jar包到服务器
根目录在/docker/mes/fcat-mes-main.jar
shell
sh deploy.sh
sh deploy.sh
curl http://192.168.9.126:16219/test/version
{
"version": "v3"
}
curl http://192.168.9.126:16220/test/version
{
"version": "v2"
}
curl http://192.168.9.126:16221/dev-api/test/version
{
"version": "v3"
}
curl http://192.168.9.126:16219/test/version
{
"version": "v3"
}
curl http://192.168.9.126:16220/test/version
{
"version": "v2"
}
curl http://192.168.9.126:16221/dev-api/test/version
{
"version": "v3"
}