0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

优雅停机是什么?SpringBoot+Nacos+k8s实现优雅停机

jf_ro2CN3Fa 来源:稀土掘金 2024-02-20 10:00 次阅读

1 概念

优雅停机是什么?网上说的优雅下线、无损下线,都是一个意思。

优雅停机,通常是指在设备、系统或应用程序中止运作前,先执行一定的流程或动作,以确保数据的安全、预防错误并保证系统的整体稳定。

一般来说,优雅停机可以参考以下步骤以实现:

备份数据 :立即将内存中的所有未保存的修改、缓存等数据保存到数据库或磁盘中。

停止接收新的请求

处理未完成的请求

通知其他依赖组件

等待所有要素安全退出后,关闭系统

在具体实施时,不同的设备、不同的系统、不同的应用,所需要的优雅停机步骤也不尽相同,甚至需要根据不同的场景来选择不同的方法。

例如,在某些情况下,你可能需要让用户知道,系统即将关闭,并告诉他们应当保存所有的工作并退出系统;而在另一些情况下,你可能需要设计一种策略,能够让系统在无用户介入的情况下,自动保存所有的状态,并在下次启动时恢复之。

但是,无论在哪种情况下,优雅停机的目标都是保护数据,避免错误,并尽量减少到访用户或使用者的不便。

上面的步骤,其实还缺了不少基础的内容,比如,停止请求外,还要停止接收定时任务、停止接收mq消息,等待他们的完成,这2项都是我们微服务中必不可缺的能力。

因此,我希望通过本文,能够更清晰,更详细的讲解,在我已知的真实业务场景下,如何做优雅停机。

文中,很多内容不会讲得太详细,需要大家有一定的搜索能力或者经验!

2 用案例说话

随着微服务的兴起,运维方式由docker -> k8s 变化,优雅停机涉及到的点就越来越多!下面,我们用一个案例,说明优雅停机中的问题和问题解决方案。

案例前:k8s 停机流程

程序员执行 kubectl delete pod 命令时,两个过程开始:

网络规则即将生效:

Kube-apiserver 收到 pod 删除请求,并将 pod 的状态更新为 Extinating at Etcd;

终结点控制器从终结点对象中删除 Pod 的 IP;

Kuber-proxy 根据 Endpoint 对象的更改更新 iptables 的规则,并且不再将流量路由到已删除的 pod。

删除容器:

Kube-apiserver 收到 pod 删除请求,并将 pod 的状态更新为 Extinating at Etcd;

Kubelet 清理节点处的容器相关资源,如存储、网络;

添加 Prestop hook 钩子,等待流量不再发给pod;

Kubelet 将SIGTERM发送到容器;

如果容器在默认的 30 秒内没有退出,Kubelet 将发送 SIGKILL 并强制其退出。

71ee3aec-cf90-11ee-a297-92fbcf53809c.jpg

k8s + springboot + nacos 案例

71f9a83c-cf90-11ee-a297-92fbcf53809c.jpg

PreStopHook 做了2件事情:

nacos反注册

休眠35秒

通过信号量关闭springboot程序;

其中,k8s的 terminationGracePeriodSeconds(宽限期)设置为35s。

问题

springBoot程序关闭时间只有2s, 那么该程序就无法处理完一些线程任务、异步消息、定时任务等。为什么呢?

宽限期设置了35s,PreStop休眠了35s + 一个请求的时间,超过了宽限期,那么 kubelet 就会给与 pod 增加一次性2s的宽限时间。Pod 的生命周期,2s不管程序是否正常结束,都会被Kill -9。

为什么反注册之后需要休眠35s?

这里涉及到nacos服务发现原理,nacos服务变更响应时间:实时;ribbon 默认缓存刷新时间30s;因此,一开始是设置30s的,发现还有feign请求失败的情况,所以设置成了35s以解决这个问题!

nacos服务变更响应时间真的是实时吗?

其实并不一定,nacos服务发现是通过http和udp实现的,udp是实时的,http最大等待时间是10s,但是,udp端口生产环境可能没有开放!所以,案例中的nacos服务发现仅通过http定时轮询实现。

案例优化

上面的案例可以优化的点

nacos 反注册后休眠35s,是否可以减少;

terminationGracePeriodSeconds 设置多少合理?

优化点1

反注册后休眠的35s时候受到nacos服务发现 + ribbon 缓存刷新时间影响,正常应该是 服务发现时间 + 缓存刷新时间 40s才能在极端情况下保证服务停机时,不会再有feign 请求进入。

如果想要缩短这个时间

启用udp,这个需要和运维同学商量,否则10s等待少不了;

监听nacos服务变更通知,发现服务下线后,及时刷新ribbon缓存;

/**
*订阅nacos实例变更通知
*手动刷新ribbon服务实例缓存
*nacosclient1.4.6【1.4.1有重大缺陷,要注意】
*/
@Component
@Slf4j
publicclassNacosInstancesChangeEventListenerextendsSubscriber{

@Resource
privateSpringClientFactoryspringClientFactory;

@PostConstruct
publicvoidregisterToNotifyCenter(){
NotifyCenter.registerSubscriber(this);
}
@Override
publicvoidonEvent(InstancesChangeEventevent){
Stringservice=event.getServiceName();
//service:DEFAULT_GROUP@@demoribbonService:demo
StringribbonService=service.substring(service.indexOf("@@")+2);
log.info("####接收到微服务nacos实例变更事件:{}ribbonServiceName:{}",event.getServiceName(),ribbonService);
ILoadBalancerloadBalancer=springClientFactory.getLoadBalancer(ribbonService);
if(loadBalancer!=null){
((ZoneAwareLoadBalancer)loadBalancer).updateListOfServers();
log.info("刷新 ribbon 服务实例:{}缓存成功",ribbonService);
}
}

@Override
publicClasssubscribeType(){
returnInstancesChangeEvent.class;
}


/**
*nacos1.4.4~1.4.6需要加这个方法的实现,2.1.2以后版本修复了该问题
*多注册中心时,变更事件没有隔离,因此需要实现该方法来判断事件是否需要处理
*@seeISSUE#8428-NacosInstancesChangeEventScope
***/
@Override
publicbooleanscopeMatches(InstancesChangeEventevent){
returntrue;
}

}

优化点2

terminationGracePeriodSeconds 的值应该略大于 PreStop耗时 + springBoot 停机时间,springBoot 停机时间是由程序业务决定的(mq消息、定时任务、线程池任务、以及备份数据),网上的推荐做法是启用springBoot的优雅停机功能,并实现自定义的关闭逻辑。

springBoot优雅停机的默认缓冲时间是30s,因此,terminationGracePeriodSeconds的时间个人建议10 + 30s即可。

经过优化后

720a365c-cf90-11ee-a297-92fbcf53809c.jpg

使用 actuator shutdown 方案

有些网贴推荐使用 actuator shutdown 进行优雅停机,那么看下其流程图:

7219a97a-cf90-11ee-a297-92fbcf53809c.jpg

其实,真正的情况并非如上图所示,因为调用shutdown后,springBoot就会进入优雅停机流程,但是这个流程没有结束,然后就会被kill -15 中断,如果线程池没有做好配置,线程池任务没有结束,服务就会关闭。

//没有设置下面参数,在kill-15时,线程池没有执行结束,会被强制关闭
threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
threadPoolTaskExecutor.setAwaitTerminationSeconds(30);

3 再次优化

mq 和 定时任务

上面的方案中,提到nacos反注册时,其他服务监听反注册事件,进行ribbon缓存刷新,那么,反注册的服务(停机服务)自身,是否可以也监听该事件呢?答案是可以的。

停机的服务监听nacos反注册事件,判断是自己反注册了,表示准备关机,那么就可以停止对mq消息的监听,停止定时任务,这样就比在优雅停机时,进行mq 和 定时任务的停止更完美。

724143fe-cf90-11ee-a297-92fbcf53809c.jpg

流量控制

如果没有使用k8s进行pod节点的流量控制,那么大概率会使用 springCloud gateway作为服务网关,因此,gateway 服务也应该监听nacos的反注册事件,从而及时刷新ribbon的缓存,关闭停机服务的流量。

4 小结

经过大量的资料参考、学习,最终得到的一份自己认为合格的优雅停机方案,里面可能有较多的不专业表述,敬请谅解和指正,谢谢。

在本文的最后,还要说下,优雅停机最大的挑战并不是来源于这个优雅停机流程,机械化的流程前人都帮忙躺过了,剩下的是业务服务自身的逻辑:

有没有包含超过30s的业务逻辑,如执行超过30s的请求,定时任务、线程池任务或mq消息;

服务关闭时,如何保存未完成的任务、数据,实现自定义的关闭逻辑;

接口逻辑是否做了幂等;





审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 控制器
    +关注

    关注

    112

    文章

    16356

    浏览量

    177973
  • UDP通信
    +关注

    关注

    0

    文章

    21

    浏览量

    1903
  • nacos
    +关注

    关注

    0

    文章

    10

    浏览量

    199

原文标题:SpringBoot + Nacos + k8s 优雅停机

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    STM8可以设置类似停机模式下闹铃唤醒吗?

    请问STM8可以设置类似停机模式下闹铃唤醒吗,比如每天8点钟从停机模式唤醒
    发表于 05-08 07:09

    stm8s003停机后,外部中断有时候会无法退出停机状态,为什么?

    stm8s003,进入停机,外部中断退出停机,但是经常会触发中断之后却没退出停机状态,再触发才行,这是什么问题。我用示波器看过外部中断的波形,确实有触发波形了,但是却没有退出
    发表于 05-11 08:29

    STM8S103K停机模式且关闭flash时有时候不能唤醒是怎么回事?

    STM8S103K停机模式且关闭flash 时有时候不能唤醒! 做一个产品,电池供电,有一个电源按键用来开关机,长按2秒就执行。用的是PE5外部中断来唤醒。 假如我设置:FLASH_CR1
    发表于 05-17 06:55

    神舟优雅U10R上网本 参考价格:2499元

    。精巧散热设计 动力强劲更环保  优雅U10R采用先进的英特尔Atom N270处理器,它是目前PC业界最小的处理器(较一般笔记本电脑CPU缩小60%),采用45纳米Hi-k金属栅极技术生产,仅
    发表于 07-01 22:30

    热门低价3G上网本推荐 神舟优雅U20Y 参考售价:2399元

    3G是第三代无线通讯技术的简称,这一代技术包括TD-SCDMA、WCDMA、CDMA2000和WiMax这四种,传统意义上的3G标准是只前三种,也正是前三种可以真正摆脱线的束缚,实现无线广域网。现在
    发表于 07-02 09:03

    stm32停机

    大家好,请教一个问题:我用stm32f103c8作为主控通过功率驱动威廉希尔官方网站 来控制一个有刷直流电机,当电机速度增大(增大PWM占空比)到一定程度时,stm32就停机了,PWM停止没有输出,其他功能也停止
    发表于 12-19 08:49

    如何优雅地完成倒计时定时器自适应显示呢

    如何实现倒计时的基本功能呢?如何优雅地完成倒计时定时器自适应显示呢?
    发表于 10-27 07:15

    利用golang优雅实现单实例分享

    1、利用golang优雅实现单实例平时编写代码过程中,经常会遇到对于全局角度只需运行一次的代码,比如全局初始化操作,设计模式中的单例模式。针对单例模式,java中又出现了饿汉模式、懒汉模式,再配
    发表于 10-17 16:46

    怎么判断STM8是否进入的停机模式?

    怎么判断STM8是否进入的停机模式
    发表于 10-09 07:01

    光电控制自动停机

    光电控制自动停机
    发表于 10-13 11:30 421次阅读

    关于SpringBoot如何优雅的全局异常处理

    SpringBoot全局异常准备说明:如果想直接获取工程那么可以直接跳到底部,通过链接下载工程代码。 开发准备 环境要求JDK:1.8SpringBoot:1.5.17.RELEASE 首先还是
    的头像 发表于 05-31 14:25 1631次阅读
    关于<b class='flag-5'>SpringBoot</b>如何<b class='flag-5'>优雅</b>的全局异常处理

    华为云微服务引擎0停机迁移Nacos?它是这样做的

    华为云微服务引擎| 0停机迁移Nacos? “它”是这样做的 迁移云环境****场景 • 微服务规模小,使用微服务引擎CSE成本太高。 • dubbo/Nacos微服务架构改造
    的头像 发表于 12-29 20:01 769次阅读

    K8s+SpringBoot实现零宕机发布

    K8s + SpringBoot实现零宕机发布:健康检查+滚动更新+优雅停机+弹性伸缩+Prometheus监控+配置分离(镜像复用)。
    的头像 发表于 01-31 16:31 941次阅读

    冰箱不停机的故障维修

    发现冰箱不停机故障应及时维修,因为冰箱不停机故障很容易造成压缩机损坏烧毁。
    的头像 发表于 02-07 09:44 4854次阅读

    Tokio 模块的优雅停机机制

    在进行高并发、网络编程时,优雅停机是一个非常重要的问题。在 Rust 语言中,Tokio 是一个非常流行的异步编程框架,它提供了一些优雅停机的机制,本文将围绕 Tokio 模块的
    的头像 发表于 09-19 15:26 637次阅读