jenkins springCloud项目优雅下线
文章目录
- 场景
- 解决
- 下线请求效果如图
- 贴一个可用的部署脚本
场景
- 在 Spring Cloud 项目的微服务实例关闭时,需要首先从注册中心设置为下线,避免该服务的消费者继续请求该服务实例,导致请求失败
- 如果我们在服务实例从注册中心取消注册后,立即销毁其它 Spring Bean 的话,会导致当前在处理的请求,又或者服务消费者因为注册中心延迟期间继续打进来的请求,产生处理失败的情况
- 在 Spring 容器关闭时,Spring Cloud 内置的 AbstractAutoServiceRegistration 会将当前实例从注册中心取消注册,但是并不能保证这个步骤最先执行,在所有 Bean 的销毁之前。同时,虽然当前服务实例已经从注册中心取消注册,但是服务消费者从注册中心中拉取到最新的注册信息,是存在延迟的,只是长短的差别。
解决
- 通过actuator/service-registry/ 接口完成接口下线
- sleep 30秒之后 再进行微服务jar包的启停
- 进行健康检查
下线请求效果如图
贴一个可用的部署脚本
#!/bin/bash
set -e# 基础
# export JAVA_HOME=/work/programs/jdk/jdk1.8.0_181
# export PATH=PATH=$PATH:$JAVA_HOME/bin
# export CLASSPATH=$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarDATE=$(date +%Y%m%d%H%M)
# 基础路径
BASE_PATH=/home/vagrant/data/workProjects/JenkinsSpringCloudDemo
# 编译后 jar 的地址。部署时,Jenkins 会上传 jar 包到该目录下
SOURCE_PATH=$BASE_PATH/build
# 服务名称。同时约定部署服务的 jar 包名字也为它。
SERVER_NAME=JenkinsSpringCloudDemo
# 环境
PROFILES_ACTIVE=prod
# 健康检查 URL
HEALTH_CHECK_URL=http://127.0.0.1:8078/actuator/health/
# 修改状态 URL
STATUS_URL=http://127.0.0.1:8078/actuator/service-registry/# heapError 存放路径
HEAP_ERROR_PATH=$BASE_PATH/heapError
# JVM 参数
JAVA_OPS="-Xms1024m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$HEAP_ERROR_PATH"
# JavaAgent 参数。可用于配置 SkyWalking 等链路追踪
JAVA_AGENT=# 备份
function backup() {# 如果不存在,则无需备份if [ ! -f "$BASE_PATH/$SERVER_NAME.jar" ]; thenecho "[backup] $BASE_PATH/$SERVER_NAME.jar 不存在,跳过备份"# 如果存在,则备份到 backup 目录下,使用时间作为后缀elseecho "[backup] 开始备份 $SERVER_NAME ..."cp $BASE_PATH/$SERVER_NAME.jar $BASE_PATH/backup/$SERVER_NAME-$DATE.jarecho "[backup] 备份 $SERVER_NAME 完成"fi
}# 最新构建代码 移动到项目环境
function transfer() {echo "[transfer] 开始转移 $SERVER_NAME.jar"# 删除原 jar 包if [ ! -f "$BASE_PATH/$SERVER_NAME.jar" ]; thenecho "[transfer] $BASE_PATH/$SERVER_NAME.jar 不存在,跳过删除"elseecho "[transfer] 移除 $BASE_PATH/$SERVER_NAME.jar 完成"rm $BASE_PATH/$SERVER_NAME.jarfi# 复制新 jar 包echo "[transfer] 从 $SOURCE_PATH 中获取 $SERVER_NAME.jar 并迁移至 $BASE_PATH ...."cp $SOURCE_PATH/$SERVER_NAME.jar $BASE_PATHecho "[transfer] 转移 $SERVER_NAME.jar 完成"
}# 停止
function stop() {echo "[stop] 开始停止 $BASE_PATH/$SERVER_NAME"PID=$(ps -ef | grep $BASE_PATH/$SERVER_NAME | grep -v "grep" | awk '{print $2}')# 如果 Java 服务启动中,则进行关闭if [ -n "$PID" ]; then# 从注册中心下线echo "[stop] 从注册中心下线当前实例,并 sleep 20 秒"curl -X POST $STATUS_URL -d '{"status": "DOWN"}' -H 'content-type: application/json'sleep 20# 正常关闭echo "[stop] $BASE_PATH/$SERVER_NAME 运行中,开始 kill [$PID]"kill -15 $PID# 等待最大 60 秒,直到关闭完成。for ((i = 0; i < 60; i++))dosleep 1PID=$(ps -ef | grep $BASE_PATH/$SERVER_NAME | grep -v "grep" | awk '{print $2}')if [ -n "$PID" ]; thenecho -e ".\c"elseecho '[stop] 停止 $BASE_PATH/$SERVER_NAME 成功'breakfidone# 如果正常关闭失败,那么进行强制 kill -9 进行关闭if [ -n "$PID" ]; thenecho "[stop] $BASE_PATH/$SERVER_NAME 失败,强制 kill -9 $PID"kill -9 $PIDfi# 如果 Java 服务未启动,则无需关闭elseecho "[stop] $BASE_PATH/$SERVER_NAME 未启动,无需停止"fi
}# 启动
function start() {# 开启启动前,打印启动参数echo "[start] 开始启动 $BASE_PATH/$SERVER_NAME"echo "[start] JAVA_OPS: $JAVA_OPS"echo "[start] JAVA_AGENT: $JAVA_AGENT"echo "[start] PROFILES: $PROFILES_ACTIVE"# 开始启动BUILD_ID=dontKillMe nohup java -server $JAVA_OPS $JAVA_AGENT -jar $BASE_PATH/$SERVER_NAME.jar --spring.profiles.active=$PROFILES_ACTIVE &echo "[start] 启动 $BASE_PATH/$SERVER_NAME 完成"
}# 健康检查
function healthCheck() {# 如果配置健康检查,则进行健康检查if [ -n "$HEALTH_CHECK_URL" ]; then# 健康检查最大 60 秒,直到健康检查通过echo "[healthCheck] 开始通过 $HEALTH_CHECK_URL 地址,进行健康检查";for ((i = 0; i < 60; i++))do# 请求健康检查地址,只获取状态码。result=`curl -I -m 10 -o /dev/null -s -w %{http_code} $HEALTH_CHECK_URL || echo "000"`# 如果状态码为 200,则说明健康检查通过if [ "$result" == "200" ]; thenecho "[healthCheck] 健康检查通过";break# 如果状态码非 200,则说明未通过。sleep 1 秒后,继续重试elseecho -e ".\c"sleep 1fidone# 健康检查未通过,则异常退出 shell 脚本,不继续部署。if [ ! "$result" == "200" ]; thenecho "[healthCheck] 健康检查不通过,可能部署失败。查看日志,自行判断是否启动成功";tail -n 10 nohup.outexit 1;# 健康检查通过,打印最后 10 行日志,可能部署的人想看下日志。elsetail -n 10 nohup.outfi# 如果未配置健康检查,则 slepp 60 秒,人工看日志是否部署成功。elseecho "[healthCheck] HEALTH_CHECK_URL 未配置,开始 sleep 60 秒";sleep 60echo "[healthCheck] sleep 60 秒完成,查看日志,自行判断是否启动成功";tail -n 50 nohup.outfi
}# 部署
function deploy() {cd $BASE_PATH# 备份原 jarbackup# 停止 Java 服务stop# 部署新 jartransfer# 启动 Java 服务start# 健康检查healthCheck
}deploy
相关文章:

jenkins springCloud项目优雅下线
文章目录 场景解决下线请求效果如图贴一个可用的部署脚本 场景 在 Spring Cloud 项目的微服务实例关闭时,需要首先从注册中心设置为下线,避免该服务的消费者继续请求该服务实例,导致请求失败如果我们在服务实例从注册中心取消注册后ÿ…...
indexOf
可以通過String的indexOf判斷是否包括某個字符。 SpringBootTest Slf4j class BaseApplicationTests {Testvoid contextLoads() {log.info("01".indexOf(".")"");log.info("0.1".indexOf(".")"");log.info("…...
STM32分区跳转问题
项目场景: 在OTA中,FLASH通常被划分为以下几种类型 bootloaderiapappbootloaderappapp保存区bootloaderapp1app2 不同的分区方式有不同的有点,但是共同点都是需要执行分区跳转 问题1描述 但在分区跳转过程中遇到过使用不同的编译器不能跳转…...

亿级流量架构服务降级
什么是服务降级 如果看过我前面对服务限流的分析,理解服务降级就很容易了,对于一个景区,平时随便进出,但是一到春节或者十一国庆这种情况客流量激增,那么景区会限制同时进去的人数,这叫限流,那么什么是服务降级呢? 简单来说就是,将一些不太重要的景区项目砍掉,平时就那么三五…...

【技术分享】RK3399 Ubuntu通过Python实现录音和播放功能
本文基于IDO-SBC3968 Ubuntu 系统通过Python脚本实现录音和播放功能。 IDO-SBC3968采用RK3399国产六核64位CPU高性能处理器,支持4K HDMI2.0显示,接口丰富,拥有千兆以太网,全协议TypeC接口,USB3.0 ,eDP 和…...

关于vs code Debug调试时候出现“找不到任务C/C++: g++.exe build active file” 解决方法
vs code Debug调试时候出现“找不到任务C/C: g.exe build active file” ,出现报错,Debug失败 后来经过摸索和上网查找资料解决问题 方法如下 在Vs code的操作页面左侧有几个配置文件 红框里的是需要将要修改的文件 查看tasks.json和launch.json框选&…...

交叉导轨在光学工作台起什么重要作用?
光学工作台常常需要承载和移动各种光学元件和仪器,如望远镜、显微镜、光谱仪等,这些设备需要在空间中进行精确的定位和稳定支撑,而交叉导轨作为一种高精度、高刚度的直线传动元件,为光学工作台提供了重要的支撑和导向。 1>交叉…...

易点易动固定资产管理系统:实现固定资产与财务系统的高效对接
在企业的日常运营中,固定资产的管理和财务账目的记录是两项不可或缺的任务。然而,由于传统的管理方式存在数据孤岛和信息不一致等问题,往往导致工作效率低下和管理混乱。为了解决这一问题,易点易动固定资产管理系统应运而生。该系…...

做亚马逊多久可以赚钱?做亚马逊需要多少资金?——站斧浏览器
做亚马逊需要时间、资金和全面的市场策略。创业者需要有耐心和决心,同时也要灵活应对市场变化。那么做亚马逊多久可以赚钱,做亚马逊需要多少资金。 做亚马逊多久可以赚钱 首先,就像任何其他生意一样,做亚马逊需要时间和努力来建立起稳定的客…...
计算机应用基础_错题集_基础知识---网络教育统考工作笔记006
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、基础知识部分错题集总结前言 计算机应用基础统考,错题集总结 一、基础知识部分 基础知识部分 2、微处理器芯片的位数即指______。 A.速度 B.字长 C....
C#面试题3
1.请解释一下C#中的并发编程和线程安全性。 并发编程是指在多线程环境下编写代码以实现并发执行的能力。C#提供了一些机制来支持并发编程,如线程、任务和并行循环等。线程安全性是指在多线程环境下,代码能够正确地处理共享数据并保持一致性。线程安全的代…...

MariaDB(基础信息)
文章目录 一、MariaDB1、基本信息2、存储引擎3、兼容性》MySQL、Postgres、MongoDB 和 Oracle4、直接连接其他数据源5、等等等。。。。。。。。。。。。。。。。。。。。。 二、操作和mysql一样参考文章 --------------------机翻内容仅供参考------------------------- 一、…...

SpringBoot + 通义千问 + 自定义React组件,支持EventStream数据解析!
一、前言 大家好!我是sum墨,一个一线的底层码农,平时喜欢研究和思考一些技术相关的问题并整理成文,限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。 最近ChatGPT非常受欢迎,尤其是…...

Redis中文结果查看方式
背景 当使用redis时我们存储到缓存中可能会包含一些中文,例如下面命令 set test 中国 当执行查看时,发现客户端显示的并不是中文而是乱码,例如下面结果 get test \xe4\xb8\xad\xe5\x9b\xbd 现对【\xe4\xb8\xad\xe5\x9b\xbd】的查看有如下几个方式 方式一:通过客户端直…...

计算机组成原理-磁盘存储器
文章目录 总览外存储器磁盘存储器磁盘的性能指标磁盘地址磁盘的工作过程磁盘阵列 总结 总览 外存储器 磁盘存储器 写是利用电流产生磁场从而写磁盘 读是利用载磁体移动时产生的电场从而得到数据 磁性材质易受外界磁场干扰 下图中 载磁体上N S的前后顺序代表对应存储二进制的比…...

连接docker swarm和凌鲨
docker swarm相比k8s而言,部署和使用都要简单很多,比较适合中小研发团队。 通过连接docker swarm和凌鲨,可以让研发过程中的常用操作更加方便。 更新容器镜像调整部署规模查看日志运行命令 使用步骤 部署swarm proxy 你可以通过linksaas…...
Qt实现画的图片移动
要实现左键点击鼠标时图片跟着鼠标移动,可以通过以下步骤来实现:1. 在QGraphicsView的构造函数中设置鼠标跟踪属性,以便能够捕获鼠标事件。cpp QGraphicsView::QGraphicsView(QWidget *parent) : QGraphicsView(parent) {setMouseTracking(tr…...

比较2个点的3种结构在不规则平面上的占比
2 2 2 1 2 2 2 2 2 1 2 2 2 2 2 1 2 2 3 3 3 x 3 3 2 2 2 1 2 2 2 2 2 1 2 2 在平面上有一个点x,再增加一个点,11的操作把平面分成了3部分2a1,2a2,2a3,3部分的比值是 2a1 2a2 2a3 5 25 …...

最小二乘线性回归
线性回归(linear regression):试图学得一个线性模型以尽可能准确地预测实际值的输出。 以一个例子来说明线性回归,假设银行贷款会根据 年龄 和 工资 来评估可放款的额度。即: 数据:工资和年龄&…...

【django+vue】连接数据库、登录功能
笔记为自我总结整理的学习笔记,若有错误欢迎指出哟~ 【djangovue专栏】 1.【djangovue】项目搭建、解决跨域访问 【djangovue】连接数据库、登录功能 django连接数据库1.安装MySQL驱动程序2.创建数据库3.配置settings.py文件4.创建表5.添加数据 登录功能1.django实现…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...