Spring boot 2.3优雅下线,距离生产还有多远?

简介: 对于任何一个线上应用,如何在服务更新部署过程中保证业务无感知是开发者必须要解决的问题,即从应用停止到重启恢复服务这个阶段不能影响正常的业务请求,这使得无损下线成为应用生命周期中必不可少的一个环节。

前言

在生产环境中,随着云原生架构的发展,自动的弹性伸缩、滚动升级、分批发布等云原生能力让用户享受到了资源、成本、稳定性的最优解。但是在应用的缩容、发布等过程中,由于实例下线处理得不够优雅,将会导致短暂的服务不可用,短时间内业务监控会出现大量 io 异常报错;如果业务没做好事务,那么还会引起数据不一致的问题,那么需要紧急手动订正错误数据;甚至每次发布,您需要发告示停机发布,否则您的用户会出现一段时间服务不可用。没处理好服务实例下线,无论发生上述哪种情况,都会对您业务的连续性造成困扰。

对于任何一个线上应用,如何在服务更新部署过程中保证业务无感知是开发者必须要解决的问题,即从应用停止到重启恢复服务这个阶段不能影响正常的业务请求,这使得无损下线成为应用生命周期中必不可少的一个环节。

同时在多次 Dubbo Meetup 中,平滑上下线一直都是位居微服务开发痛点前 Top 3。

下面我们来了解一下 Spring Boot 2.3 中提供的新特性 Graceful Shutdown,来分析一下它对我们生产稳定性带来什么样的帮助。

Spring Boot graceful shutdown

Graceful shutdown

Graceful shutdown is supported with all four embedded web servers (Jetty, Reactor Netty, Tomcat, and Undertow) and with both reactive and Servlet-based web applications. When enabled using server.shutdown=graceful, upon shutdown, the web server will no longer permit new requests and will wait for a grace period for active requests to complete. The grace period can be configured using spring.lifecycle.timeout-per-shutdown-phase. Please see the reference documentation for further details.

Spring Boot 2.3.0.RELEASE引入了Graceful Shutdown的功能。其中应用在等待下线期间对待新请求的方式,取决于我们所使用的 Server 类型。根据官方文档Tomcat、Jetty 和 Reactor Netty将会在网络层面停止接收新的请求。Undertow 会继续接收新的请求,但立即会以 HTTP 503(服务不可用)来响应。

配置与使用

在Spring Boot 2.3.0中,优雅停机的使用非常简单,可以通过在应用程序配置文件中设置两个属性来进行。
1、 server.shutdown 属性可以支持的值有两种

  1. immediate 这是默认值,配置后服务器立即关闭,无优雅停机逻辑。
  2. graceful 开启优雅停机功能,并遵守 spring.lifecycle.timeout-per-shutdown-phase 属性中给出的超时来作为服务端等待的最大时间。
    2、spring.lifecycle.timeout-per-shutdown-phase 服务端等待最大超时时间,采用java.time.Duration格式的值,默认30s。

例如:Properties 文件

1、#To enable graceful shutdown

2、server.shutdown=graceful
3、#To configure the timeout period
4、spring.lifecycle.timeout-per-shutdown-phase=20s

当我们使用了如上配置开启了优雅停机功能,当我们通过SIGTERM信号关闭 Spring Boot 应用时
1、 此时如果应用中没有正在进行的请求,应用程序将会直接关闭,而无需等待超时时间结束后才关闭。
2、此时如果应用中有正在处理的请求,则应用程序将等待超时时间结束后才会关闭。如果应用在超时时间之后仍然有未处理完的请求,应用程序将抛出异常并继续强制关闭。

源码实现分析

我们以 Tomcat 为例看一下是SpringBoot 2.3如何实现graceful shutdown的

这里注意下,Tomcat 9.0.33或更高版本,才具备graceful shutdown功能。

我们看一下 SpringBoot 的 TomcatWebServer 的实现,先看其中构造函数

1、org.springframework.boot.web.embedded.tomcat.TomcatWebServer

2、public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) {
3、 Assert.notNull(tomcat, "Tomcat Server must not be null");
4、 this.tomcat = tomcat;
5、 this.autoStart = autoStart;
6、 this.gracefulShutdown = (shutdown == Shutdown.GRACEFUL) ? new GracefulShutdown(tomcat) : null;
7、 initialize();
8、}

可以看到当我们配置 server.shutdown=graceful 时,其中 gracefulShutdown 成员就不为null,而是被置为 GracefulShutdown 实例。
当我们关闭SpringBoot的应用容器时,会触发其生命周期的 stop 方法,我们看到其中会执行webServer的shutDownGracefully方法
image.png
因为我们配置 了server.shutdown=graceful ,所以 gracefulShutdown 成员并不为null,而是会触发 gracefulShutdown 的 shutDownGracefully 方法
image.png
我们看一下shutDownGracefully 方法是如何做到graceful shutdown的
image.png

来看一下doShutdown的逻辑
org.springframework.boot.web.embedded.tomcat.GracefulShutdown#doShutdown
private void doShutdown(GracefulShutdownCallback callback) {

List<Connector> connectors = getConnectors();
connectors.forEach(this::close);
try {for (Container host : this.tomcat.getEngine().findChildren()) {for (Container context : host.findChildren()) {while (isActive(context)) {if (this.aborted) {logger.info("Graceful shutdown aborted with one or more requests still active");callback.shutdownComplete(GracefulShutdownResult.REQUESTS_ACTIVE);return;}Thread.sleep(50);}}}}
catch (InterruptedException ex) {Thread.currentThread().interrupt();
}
logger.info("Graceful shutdown complete");
callback.shutdownComplete(GracefulShutdownResult.IDLE);

}

先是关闭掉所有的连接,在网络层停止接受请求,然后再等待所有请求处理完毕。
其中关于 spring.lifecycle.timeout-per-shutdown-phase 配置,是通过等待配置的时间后,再执行TomcatWebServer的stop方法,将其aborted成员置为true,实现如果应用在宽限期之后仍然有待处理的请求,应用程序将抛出异常并继续强制关闭,而不是一直等待下去。
@Override
public void stop() throws WebServerException {

synchronized (this.monitor) {boolean wasStarted = this.started;try {this.started = false;try {if (this.gracefulShutdown != null) {this.gracefulShutdown.abort();}stopTomcat();this.tomcat.destroy();}catch (LifecycleException ex) {// swallow and continue}}catch (Exception ex) {throw new WebServerException("Unable to stop embedded Tomcat", ex);}finally {if (wasStarted) {containerCounter.decrementAndGet();}}
}

}

void abort() {

this.aborted = true;

}

在微服务场景下问题似乎依旧存在...
总结一下一个 Spring Cloud 应用正常分批发布的流程
1、服务发布前,消费者根据负载均衡规则调用服务提供者,业务正常。
2、服务提供者 B 需要发布新版本,先对其中的一个节点进行操作,先是正常停止 Java 进程。
3、服务停止过程中,首先去注册中心注销服务,然后等待服务端线程处理完成,再停止服务。
4、注册中心则将通知消费者,其中的一个服务提供者节点已下线。这个过程包含推送和轮询两种方式,推送可以认为是准实时的,轮询的耗时由服务消费者轮询间隔决定,最差的情况下需要 1 分钟。
5、服务消费者刷新服务列表,感知到服务提供者已经下线了一个节点,但是这个过程中Spring Cloud 的负载均衡组件 Ribbon 默认的刷新时间是 30 秒 ,最差情况下需要耗时 30 秒。
6、服务消费者不再调用已经下线的节点
image.png

我们看到,当一个Spring Cloud服务端通过SpringBoot提供的graceful shutdown下线时,它会拒绝客户端新的请求,并且等待已经在处理的线程处理完成后,或者在配置的应用最长等待时间到了之后进行下线。

但是在服务端重启开始拒绝客户端新的请求的时刻开始,即执行了Connectors.stop开始,到客户端感知到服务端该实例下线这段时间内,客户端向该实例发起的所有请求都会被拒绝,从而引起服务调用异常。

image.png
如果客户端考虑增加重试能力,这一定程度上可以缓解发布过程中服务调用报错的问题,但是无法根本上保证下线过程的无损,如果服务调用报错期过程,或者分批发布时候同一批次下线的节点数过多,无法保证仅仅增加多次重试就能够调用到未下线的节点上。这不能根本解决问题!同时需要考虑配置重试带来的业务上存在不幂等的风险。

EDAS 3.0 无损下线

EDAS 3.0 通过Java Agent技术无侵入增强您的应用,使其具备无损下线能力。
• 您无需修改一行代码与配置,天然具备无侵入特点
• 同时支持 ECS 、K8s 场景
• 全面兼容开源,支持开源Dubbo、Spring Cloud 以及开源微服务网关
image.png

EDAS的应用如何做到无损下线?

image.png
如图看到,我们通过3个步骤的增强,主动注销、服务提供者通知下线信息、服务消费者调用其他服务提供者。

可以看到,真正做到无损下线能力是需要客户端增强一起联动的

• 主动注销
我们在应用服务下线前,主动通知注册中心注销该实例
• 通知下线信息
我们会在服务端实例下线前主动通知客户端,该服务节点下线的信息
• 调用其他提供者
我们在客户端增强其负载均衡能力,在服务端下线后,客户端主动调用其他服务提供者节点
同时我们提供应用等待的逻辑,使要下线的服务端等待已经收到的请求处理完成再关闭 Spring 容器。

image.png

完整的解决方案

EDAS 3.0无损下线不仅仅支持 Spring Cloud 与 Dubbo 服务,我们还打通了消息、网关等微服务组件,让您的应用在EDAS中做到全链路的下线无损。

EDAS 3.0支持端到端的无损下线

  • 云上客户存在多种微服务网关,支持主流开源微服务网关(Spring Cloud Gateway、Zuul等)的无损下线
  • 有些用户的流量是通过 Ingress、SLB、Nginx 等方式打到服务端的场景
  • MQ消息等异步订阅关系的微服务场景
  • K8s 使用 Service 服务发现的微服务场景
    为了做到全链路的无损下线,EDAS 3.0 通过无侵入的方式涵盖多种场景的完整解决方案,确保您的发布平滑无损。

即使面对白天大流量的场景,发布依旧风轻云淡。

 

原文链接
本文为阿里云原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/514874.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

发布 128 核 Altra Max,自研内核,明年推出 5nm 处理器,“性能怪兽”Ampere 搞大事?

2015 年&#xff0c;在英特尔就职 28 年的总裁 Renee James 辞职&#xff0c;正在大众纷纷猜测她将如何开启下一段旅程时&#xff0c;她有了创业的想法&#xff0c;2017 年带领新团队创立了专注于为云和边缘打造微处理器的 Ampere 公司。 在云原生浪潮下&#xff0c;底层硬件需…

2020亚太内容分发大会 阿里云荣获“边缘计算领航企业”奖

10月21日&#xff0c;第八届亚太内容分发大会在北京隆重召开。凭借在边缘计算领域的先发优势、技术实力与丰富实践&#xff0c;阿里云荣获“边缘计算领航企业”称号。 伴随着中国5G商用进程提速&#xff0c;大带宽、大连接、低时延的应用场景爆发&#xff0c;将催生产业变革&a…

最佳途径 | 容器规模化落地如何四步走?

随着云原生时代的发展&#xff0c;传统 IT 基础设施加速云化&#xff0c;云原生化成为云上的必然趋势。作为云原生代表技术之一&#xff0c;容器技术可帮助企业提升 IT 架构的敏捷性&#xff0c;加速应用创新&#xff0c;帮助企业更加灵活地应对商业发展中的不确定性。疫情期间…

elasticsearch 嵌入式_Elasticsearch 开箱指南

内容概要ES 基础介绍&#xff0c;重点是其中的核心概念。基础 API 实践操作。1. 基础介绍Elasticsearch (ES) 是一个数据库&#xff0c;提供了分布式的、准实时搜索和分析。基于 Apache Lucene&#xff0c;可以操作结构化数据、非结构化数据、数字类型数据、地理空间数据。数据…

最良心的 chrome 插件可以良心到什么程度?

CSDN下起了红包雨399 元智能音箱199 元天猫精灵300元现金红包/会员100元红包/会员更有千万流量曝光100%有奖......作为日常总发现 " 宝藏 " 的你总体验过一些 " 王炸 " 级别的chrome插件让你想 “ 真诚 ” 安利所以&#xff0c;CSDN开启了彩虹屁chrome插件…

一文教会你如何写复杂业务代码

简介&#xff1a; 这两天在看零售通商品域的代码。面对零售通如此复杂的业务场景&#xff0c;如何在架构和代码层面进行应对&#xff0c;是一个新课题。针对该命题&#xff0c;我进行了比较细致的思考和研究。结合实际的业务场景&#xff0c;我沉淀了一套“如何写复杂业务代码”…

Day.js 常用方法

文章目录1. 初始化日期 / 时间2. 格式化日期 / 时间3. 加 / 减4. 获取某年某月的第一天或最后一天5. 获取星期几6. 获取毫秒数7. 获取时间差&#xff08;默认输出的差值单位是毫秒&#xff09;8. 获取时、分、秒9. 将毫秒转为时分秒10. 判断一个日期是否在另外一个日期之后 isA…

如何使用云原生数据湖,助力线上教育行业逐步智能化

简介&#xff1a; 阿里云基于对象存储OSS构建的数据湖解决方案&#xff0c;帮助企业有效消除数据孤岛的现象&#xff0c;让数据的价值真正被利用起来。 行业综述 线下教育行业因疫情受挫&#xff0c;线上教育却逆势增长 随着90年代互联网的引入&#xff0c;在线教育产品也依托…

caas k8s主控节点如何查询_k8s--04 部署harbor作为k8s镜像仓库

k8s实战部署harbor作为k8s镜像仓库1.实验目标部署k8s私有镜像仓库harbor把demo小项目需要的镜像上传到harbor上修改demo项目的资源配置清单&#xff0c;镜像地址修改为harbord的地址2.再node1上安装harbor[rootnode1 ~]# cd /opt/#上传harbor软件包[rootnode1 /opt]# rz -Erz w…

vue3中使用cookie

前端使用cookie 步骤一 编写方法cookie.ts //获取cookie、 const CooieTool {getCookie: (name: string) > {var arr, reg new RegExp("(^| )" name "([^;]*)(;|$)");if (arr document.cookie.match(reg))return (arr[2]);elsereturn null;},//设…

无人机、IoT 都危险?第五代网络威胁有哪些特点

从无序中寻找踪迹&#xff0c;从眼前事探索未来。2021 年正值黄金十年新开端&#xff0c;CSDN 以中立技术社区专业、客观的角度&#xff0c;深度探讨中国前沿 IT 技术演进&#xff0c;推出年度重磅企划栏目——「拟合」&#xff0c;通过对话企业技术高管大咖&#xff0c;跟踪报…

持续定义SaaS模式云数据仓库+Serverless

导读&#xff1a;今天主要和大家交流的是网易在数据湖 Iceberg 的一些思考与实践。从网易在数据仓库建设中遇到的痛点出发&#xff0c;介绍对数据湖 Iceberg 的探索以及实践之路。 主要内容包括&#xff1a; 数据仓库平台建设的痛点数据湖 Iceberg 的核心原理数据湖 Iceberg 社…

循序渐进db2 第3版_「图书推荐」焊接工程师手册第3版

机械工业出版社陈祝年 陈茂爱 著内容介绍《焊接工程师手册》(第3版)是焊接专业的综合性工具书&#xff0c;基本涵盖了焊接专业的技术内容。本版在保留第2版精华和特色的基础上添加了先进的工艺技术内容。全书共9篇58章。第1篇汇集了焊接工程师最常用而又不易记忆的符号、公式和…

阿里云推出业内首个云原生企业级数据湖解决方案:将在今年双11大规模应用

简介&#xff1a; 数据湖高峰论坛在京召开&#xff0c;阿里云宣布推出业内首个云原生企业级数据湖解决方案&#xff0c;提供EB级数据存储、分析能力&#xff0c;可一站式实现湖存储、湖加速、湖管理、湖计算&#xff0c;帮助企业对数据深入挖掘与分析&#xff0c;洞察其中蕴含的…

Serverless对研发效能的变革和创新

对企业而言&#xff0c;Serverless 架构有着巨大的应用潜力。随着云产品的完善&#xff0c;产品的集成和被集成能力的加强&#xff0c;软件交付流程自动化能力的提高&#xff0c;我们相信在 Serverless 架构下&#xff0c;企业的敏捷性有 10 倍提升的潜力。本次分享我主要分为以…

c3p0 服务启动获取连接超时_微服务架构中的熔断、降级

微服务架构中熔断和降级是保证服务高可用的一项重要功能点&#xff0c;微服务区别于一体化项目的最大区别也再于熔断和降级&#xff0c;很多微服务项目的开发人员对熔断的理解就是当服务不可用的时候&#xff0c;为了让整体服务可以正常运行&#xff0c;需要让后续的请求直接返…

重塑APM标杆,博睿数据战略升级助力企业数字化转型

&#xff08;博睿数据发布仪式&#xff09; 2021年5月26日&#xff0c;由博睿数据举办的“服务可达 达者为先博睿数据2021年战略升级发布巡展”北京站&#xff0c;在北京金茂威斯汀大饭店圆满举行&#xff01;本次战略升级发布巡展不仅揭开了“数据链DNA”的神秘面纱&#xff…

持续定义SaaS模式云数据仓库+数据银行

简介&#xff1a; 本文将介绍SaaS模式云数据仓库MaxCompute&#xff0c;如何助力数据银行SaaS模式云战略和一体化数据开放场景介绍。 一、云数据仓库 本章节介绍云数据仓库带来的价值及解决方案。 MaxCompute&#xff1a;SaaS模式企业级云数据仓库的应用场景包括广告场景-用…

2020-10-28

Kubernetes的门户-Ingress 目前Kubernetes&#xff08;K8s&#xff09;已经真正地占领了容器编排市场&#xff0c;是默认的云无关计算抽象&#xff0c;越来越多的企业开始将服务构建在K8s集群上。在K8s中&#xff0c;组件通过Service对外暴露服务&#xff0c;常见的包括NodePo…

530并行日:用超算更省心

科技兴&#xff0c;则民族兴&#xff1b;科技强&#xff0c;则国家强。 从“神舟”飞天、“蛟龙”入海、“天眼”遥看宇宙&#xff0c;到“嫦娥”奔月、“天问”探火、“量子”惊叹世界&#xff0c;这些世人瞩目的科技成就背后&#xff0c;是一代又一代的中国科技工作者前赴后继…