别再用 kill -9了,这才是微服务上 下线的正确姿势

Java利用zookeeper实现服务器动态上下线感知 这个是利用Java开发,借助于zookeeper来进行节点数据存储的服务器动态上下限感知系统(原先我们有三台服务器进行不停的接受FTP数据,但是这三台服务器在运行的过程中随时都有可能掉线或者断电,这样FTP中的数据就不能实时的被传递回来,这个时候我们开发了一个用于借助zookeeper进行判断服务器是否在线的系统,完全可以使用) 立即下载

对于微服务来说,服务的优雅上下线是必要的。

就上线来说,如果组件或者容器没有启动成功,就不应该对外暴露服务,对于下线来说,如果机器已经停机了,就应该保证服务已下线,如此可避免上游流量进入不健康的机器。

优雅下线

基础下线(Spring/SpringBoot/内置容器)

首先JVM本身是支持通过shutdownHook的方式优雅停机的。

别再用 kill -9了,这才是微服务上 下线的正确姿势

 

此方式支持在以下几种场景下优雅停机:

  1. 程序正常退出
  2. 使用System.exit()
  3. 终端使用Ctrl+C
  4. 使用Kill pid干掉进程

那么如果你偏偏要kill -9 程序肯定是不知所措的。

而在Springboot中,其实已经帮你实现好了一个shutdownHook,支持响应Ctrl+c或者kill -15 TERM信号。

随便启动一个应用,然后Ctrl+c一下,观察日志就可知, 它在 AnnotationConfigEmbeddedWebApplicationContext 这个类中打印出了疑似Closing...的日志,真正的实现逻辑在其父类 AbstractApplicationContext 中(这个其实是spring中的类,意味着什么呢,在spring中就支持了对优雅停机的扩展)。

别再用 kill -9了,这才是微服务上 下线的正确姿势

 

我们能对它做些什么呢,其实很明显,在doClose方法中它发布了一个ContextClosedEvent的方法,不就是给我们扩展用的么。

于是我们可以写个监听器监听ContextClosedEvent,在发生事件的时候做下线逻辑,对微服务来说即是从注册中心中注销掉服务。

别再用 kill -9了,这才是微服务上 下线的正确姿势

 

可能会有疑问的是,微服务中一般来说,注销服务往往是优雅下线的第一步,接着才会执行停机操作,那么这个时候流量进来怎么办呢?

个人会建议是,在注销服务之后就可开启请求挡板拒绝流量了,通过微服务框架本身的故障转移功能去处理被拒绝的流量即可。另外,关注公众号Java技术栈,在后台回复:面试,可以获取我整理的 Java、Spring Boot 系列面试题和答案,非常齐全。

Docker中的下线

好有人说了,我用docker部署服务,支不支持优雅下线。

那来看看docker的一些停止命令都会干些啥:

一般来说,正常人可能会用docker stop或者docker kill 命令去关闭容器(当然如果上一步注册了USR2自定义信息,可能会通过docker exec kill -12去关闭)。

对于docker stop来说,它会发一个SIGTERM(kill -15 term信息)给容器的PID1进程,并且默认会等待10s,再发送一个SIGKILL(kill -9 信息)给PID1。

那么很明显,docker stop允许程序有个默认10s的反应时间去做一下优雅停机的操作,程序只要能对kill -15 信号做些反应就好了,如上一步描述。那么这是比较良好的方式。

当然如果shutdownHook方法执行了个50s,那肯定不优雅了。可以通过docker stop -t 加上等待时间。

外置容器的shutdown脚本(Jetty)

如果非要用外置容器方式部署(个人认为浪费资源并提升复杂度)。那么能不能优雅停机呢。

可以当然也是可以的,这里有两种方式:

首先RPC框架本身提供优雅上下线接口,以供调用来结束整个应用的生命周期,并且提供扩展点供开发者自定义服务下线自身的停机逻辑。同时调用该接口的操作会封装成一个preStop操作固化在jetty或者其他容器的shutdown脚本中,保证在容器停止之前先调用下线接口结束掉整个应用的生命周期。shutdown脚本中执行类发起下线服务 -> 关闭端口 -> 检查下线服务直至完成 -> 关闭容器的流程。

而更简单的另一种方法是直接在脚本中加入kill -15命令。

别再用 kill -9了,这才是微服务上 下线的正确姿势

 

优雅上线

优雅上线相对来说可能会更加困难一些,因为没有什么默认的实现方式,但是总之呢,一个原则就是确保端口存在之后才上线服务。

springboot内置容器优雅上线

这个就很简单了,并且业界在应用层面的优雅上线均是在内置容器的前提下实现的,并且还可以配合一些列健康检查做文章。Spring Boot 优雅关闭新姿势,看看这篇。

参看sofa-boot的健康检查的源码,它会在程序启动的时候先对springboot的组件做一些健康检查,然后再对它自己搞得sofa的一些中间件做健康检查,整个健康检查的流程完毕之后(sofaboot 目前是没法对自身应用层面做健康检查的,它有写相关接口,但是写死了port is ready...)才会暴露服务或者说优雅上线,那么它健康检查的时机是什么时候呢:

别再用 kill -9了,这才是微服务上 下线的正确姿势

 

可以看到它是监听了ContextRefreshedEvent这个事件。在内置容器模式中,内置容器模式的start方法是在refreshContext方法中,方法执行完成之后发布一个ContextRefreshedEvent事件,也就是说在监听到这个事件的时候,内置容器必然是启动成功了的。

但ContextRefreshedEvent这个事件,在一些特定场景中由于种种原因,ContextRefreshedEvent会被监听到多次,没有办法保证当前是最后一次event,从而正确执行优雅上线逻辑。

在springboot中还有一个更加靠后的事件,叫做ApplicationReadyEvent,它的发布藏在了afterRefresh还要后面的那一句listeners.finished(context, null)中,完完全全可以保证内置容器 端口已经存在了,所以我们可以监听这个事件去做优雅上线的逻辑,甚至可以把中间件相关的健康检查集成在这里。

别再用 kill -9了,这才是微服务上 下线的正确姿势

 

外置容器(Jetty)优雅上线

目前大多数应用的部署模式不管是jetty部署模式还是docker部署模式(同样使用jetty镜像),本质上用的都是外置容器。那么这个情况就比较困难了,至少在应用层面无法观察到外部容器的运行状态,并且容器本身没有提供什么hook给你实现。

那么和优雅上线一样,需要RPC框架提供优雅上线接口来初始化整个应用的生命周期,并且提供扩展点给开发者供执行自定义的上线逻辑(上报版本探测信息等)。同样将调用这个接口封装成一个postStart操作,固化在jetty等外置容器的startup脚本中,保证应用在容器启动之后在上线。容器执行类似启动容器 -> 健康检查 -> 上线服务逻辑 -> 健康上线服务直至完成 的流程。

别再用 kill -9了,这才是微服务上 下线的正确姿势

 

最全学习笔记:大厂真题+微服务+MySQL+分布式+SSM框架+Java+Redis+数据结构与算法+网络+Linux+Spring全家桶+JVM+高并发+各大学习思维脑图+面试集合

使用trae自动生成前后端分离的web应用程序 使用ai自动生成前后端分离的web应用程序 阅读详情

相关推荐

【网络原理】HTTP 请求 (Request)详解

【网络原理】HTTP 请求 (Request)详解,认识URLquery string关于 URL encode, GET方法,POST 方法,GET 和 POST 的区别,User-Agent (简称 UA),Referer,Cookie

ZXT的博客 1万+

别再用 kill -9 了,这才是微服务上下线的正确姿势!

点击关注公众号,Java干货及时送达作者:fredalxin地址:https://fredal.xin/graceful-soa-updown对于微服务来说,服务的优雅上下线是必要的。就上...

Java技术栈,分享最主流的Java技术 581

经典脉冲激光测距原理&雷达方程

脉冲激光测距机的工作过程如下:首先用瞄准光学系统瞄准目标,然后接通激光电源,储能电容器充电,产生触发闪光灯的触发脉冲,闪光灯点亮,激光器受激辐射,从输出反射镜发射出一个前沿陡峭、峰值功率高的激光脉冲,通过发射光学系统压缩光束发射角后射向目标。通过计算激光发射功率经介质传输的衰减,目标表面截获和反射的光功率,到达接收视场的光功率,以及接收光学系统接收到的光功率,就可以得到到达光电探测器的光功率,即接收功率。⑤光東路程上的折射率变化;),测量光脉冲到达目标并由目标返回到接收机的时间,由此计算出目标的距离。

weixin_46153372的博客 2530

不用 kill -9,让 SpringBoot 优雅停机!

先来一段简单的代码,如下: @RestController publicclassDemoController{ @GetMapping("/demo") publicStringdemo()throwsInterruptedException{ //模拟业务耗时处理流程 Thread.sleep(20*1000L); return"hello"; } } 当我们流量请求到此接口执行业务逻辑的时候,若服务端此时执行关机 (kill),spring b.........

Purpletaro的专栏 836

CCS导入工程报错?手把手教你安装C2000编译器(附最新下载链接)

本文详细解析CCS导入工程报错的常见原因,并提供三种安装C2000编译器的解决方案(TI官网离线安装、CCS内置更新和App Center渠道)。通过版本匹配技巧和路径配置要点,帮助开发者快速解决编译器缺失问题,确保项目顺利导入和编译。

weixin_30374009的博客 664

VS Code ESP-IDF无法找到源文件、头文件波浪线解决

背景:想要编译小智AI项目,可以正常编译。但是一些头文件,例如#include <nvs.h>等无法找到。

Hot_Ant的博客 1493

进程管理:kill 命令之 -9 与 -15

相关系列文章: 【Linux 系统】一个常驻进程问题的再次分析  一 进程状态转换   二 kill命令回顾 kill :发送指定的信号到相应进程。不指定信号将发送SIGTERM(15)终止指定进程。若仍无法终止该程序可用“-KILL” 参数,其发送的信号为SIGKILL(9) ,将强制结束进程,使用ps命令或者jobs 命令可以查看进程号。root用户将影响用户的进程,非root用户只能影响自己的进程。 2.1 kill命令参数 在命令行输入kill,可以看到参数提示如下:

程序员架构进阶 8985

量化 insider 爆料! 散户打板必亏?(打板必看!量化资金如何“隔日砸盘”收割散户)

量化开发 insider 爆料💥 散户追的涨停板📉,可能是机构故意做的陷阱!本文从技术视角拆解“涨停陷阱”,帮你看清市场真实逻辑🧠。

XiaoqiangClub的博客 459

springCloud服务实时上下线(基于akka集群服务)

SpringCloud基于AP架构的实现,系统内各种缓存导致服务上线无法实时响应到网关中,在不刻意调整各种缓存配置的情况下,这里基于akka集群的节点状态来实时同步服务上下线状态到网关或各依赖服务中. 具体实现原理为: eureka注册中心修改 1.eureka注册中心服务添加@EventListener的处理逻辑,获知到服务节点注册或者下线事件通知(EurekaInstanceCanceledEvent和EurekaInstanceCanceledEvent),缓存该事件对应服务节点的InstanceIn

sinat_29131797的博客 965

爆肝5万字❤️Open3D 点云数据处理基础(Python版)

本文为Open3D 点云数据处理基础教程(Python版),小白也能轻松上手!还等什么呢,学起来!

孙悟空 13万+

VHDL语法学习笔记:一文掌握VHDL语法

今天给大侠带来FPGA 之 VHDL 语法学习笔记,话不多说,上货。 VHDL语法学习笔记 一、VHDL简介 1.1 VHDL 的历史 VHDL 的 英 文 全 名 是 Very-High-Speed Integrated Circuit Hardware DescriptionLanguage,诞生于 1982 年。 1987 年底,VHDL 被 IEEE 和美国国防部确认为标准硬件描述语言。自 IEEE 公布了 VHDL 的标准版本 IEEE-1076(简称 87 版)...

2万+

Zookeeper——服务器动态上下线、客户端动态监听

Zookeeper——服务器动态上下线、客户端动态监听

贝尔摩德苦艾酒 6151

支付宝个人年度账单爬虫实战:从扫码登录到数据解析的全链路解析

作为一名数据爱好者或量化分析师,获取自己的支付宝年度账单不仅是对个人消费行为的深度复盘,更是实现"数据自主权"的第一步。print(f"{row['year']}年: 收入{row['total_income']:.2f} | 支出{row['total_expense']:.2f} | 结余{row['net_savings']:.2f}"){"category": "餐饮", "amount": 12000, "count": 345},"""打开登录页,等待用户扫码,返回Cookie字典"""

2201_76125261的博客 334

别再用 kill -9 了,这才是微服务上下线的正确姿势!(1)

如果你选择了IT行业并坚定的走下去,这个方向肯定是没有一丝问题的,这是个高薪行业,但是高薪是凭自己的努力学习获取来的,这次我把P8大佬用过的一些学习笔记(pdf)都整理在本文中了《Java中高级核心知识全面解析》小米商场项目实战,别再担心面试没有实战项目:《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!笔记(pdf)都整理在本文中了《Java中高级核心知识全面解析》[外链图片转存中…(img-0MgywStE-1712404559827)]

VIP129370的博客 957

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

SpringCloud 微服务如何实现优雅下线?

我们也可以自定义端点来实现一些自定义逻辑,自定义端点通过标记,接着可以使用或者标记方法,通过get/post请求访问/actuator/myshutdown。接着可以使用通知注册中心下线,然后等一段时间(缓存过期后)后再通过shutdown或者kill关闭服务。如下,自定义端点的缺点是绑定了,如果有一天注册中心换了这里就不能用了,而使用actuator提供的端点,一般注册中心都会实现spring cloud的标准,所以可以屏蔽具体的实现。@Autowired。

1124

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

别再用 kill -9 了,这才是微服务上下线的正确姿势!,2024年最新面试怎么学

对于docker stop来说,它会发一个SIGTERM(kill -15 term信息)给容器的PID1进程,并且默认会等待10s,再发送一个SIGKILL(kill -9 信息)给PID1。那么很明显,docker stop允许程序有个默认10s的反应时间去做一下优雅停机的操作,程序只要能对kill -15 信号做些反应就好了,如上一步描述。那么这是比较良好的方式。可能会有疑问的是,微服务中一般来说,注销服务往往是优雅下线的第一步,接着才会执行停机操作,那么这个时候流量进来怎么办呢?

2401_84104883的博客 775

微服务架构:Nacos本地缓存 PK 微服务优雅下线

在上篇文章《》中讲了当微服务突然挂掉的解放方案调整健康检查周期和故障请求重试。朋友看了文章,建议再聊聊正常关闭服务时如何让微服务优雅下线。为什么说是优雅下线?我们知道在分布式应用中为了满足CAP原则中的A(可用性),像Nacos、Eureka等注册中心的客户端都会进行实例列表的缓存。当正常关闭应用时,虽然可以主动调用注册中心进行注销,但这些客户端缓存的实例列表还是要等一段时间才会失效。...

LoveSummer 6952

Nacos——如何下线被 kill -9 的实例

上文说到了服务实例的正常上下线,都是实例主动调接口完成的。但是如果实例被kill -9呢,就不会主动通知下线了。 如何处理这种情况,这个才是服务发现的重点了。 解决的办法就是 心跳+定时任务去判断,不过这里定时任务的分配也是有讲究了。 1 心跳 nacos源码分析——如何做心跳续约 中说到了,服务实例的心跳调用/clientBeat接口,会更新lastBeat为当前时间。 但是这个lastBeat时间要如何用起来呢? 2 定时任务 VirtualClusterDomain 会起个定时任务

weixin_42073629的博客 2872

Spring Cloud 微服务优雅下线 + 灰度发布的正确姿势,写得太好了!

在生产环境中,如何保证在服务升级的时候,不影响用户的体验,这个是一个非常重要的问题。如果在我们升级服务的时候,会造成一段时间内的服务不可用,这就是不够优雅的。那什么是优雅的呢?主要就是指在服务升级的时候,不中断整个服务,让用户无感知,进而不会影响用户的体验,这就是优雅的。实际上,优雅下线是目标,而不是手段,它是一个相对的概念,例如kill PID和都是暴力杀死服务,相对于来说,kill PID就是优雅的。但如果单独拿kill PID出来说,我们能说它是优雅的下线策略吗?肯定不是啊,就是这个道理。

msbz7的博客 562
上一篇: 阿里P9封神之作!RocketMQ核心笔记疯传Ali内网
下一篇: 再见 Jenkins!几行脚本搞定自动化部署,这款神器有点厉害
奇迹摘星w
博客等级 码龄6年 1844粉丝 189原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值