• 自动秒收录
  • 软件:1973
  • 资讯:56215|
  • 收录网站:181187|

IT精英团

Spring云应用的优雅下线和灰度发布

Spring云应用的优雅下线和灰度发布

浏览次数:
评论次数:
编辑: 阳煦
信息来源: ITPUB
更新日期: 2022-05-09 18:32:45
摘要

前言在生产环境中,如何保证在服务升级的时候,不影响用户的体验,这个是一个非常重要的问题。如果在我们升级服务的时候,会造成一段时间内的服务不可用,这就是不够优雅的。那什么是优雅的呢?主要就是指在服务升级

  • 正文开始
  • 相关阅读
  • 推荐作品

前言

在生产环境中,如何保证服务升级不会影响用户体验是一个非常重要的问题。如果我们升级服务,会让服务在一段时间内不可用,不够优雅。什么是优雅?主要是指服务升级的时候,整个服务不中断,让用户没有感知,然后用户体验不会受到影响。这是优雅的。

其实,优雅的下线是目的,不是手段。这是一个相对的概念。比如kill PID和kill -9 PID都是暴力查杀服务。与kill -9 PID相比,kill PID是优雅的。但如果单拿kill PID来说,能说是优雅的线下策略吗?我肯定不是。这就是原因。

所以本文所描述的优雅下线只能称之为“相对优雅的下线”,但相对于暴力的查杀服务来说,已经足够优雅了。常见的优雅解决方案主要有优雅离线和灰度释放。其实灰度发布的范围已经包括优雅下线了。

最后,本文主要讲基于Spring Cloud和Euraka的优雅离线和灰度发布。

优雅下线

常见的下线方式

方式一:kill PID

用法:kill java进程ID

这种方法依靠Spring Boot应用的关机钩子,应用本身的下线是优雅的。但是,如果您的服务发现组件正在使用Eureka,默认情况下会有90秒的延迟,其他应用程序会感知到服务的下线,这意味着其他服务可能仍然会在实例下线后的90秒内调用下线实例。所以这个方法不够优雅。

41211">方式二:/shutdown端点

Spring Boot 提供了/shutdown端点,可以借助它实现优雅停机。

使用方式:在想下线应用的application.yml中添加如下配置,从而启用并暴露/shutdown端点:

management:
  endpoint:
    shutdown:
      enabled: true
  endpoints:
    web:
      exposure:
        include: shutdown

发送 POST 请求到/shutdown端点

curl -X http://你想停止的服务地址/actuator/shutdown

该方式本质和方式一是一样的,也是借助 Spring Boot 应用的 Shutdown hook 去实现的。

方式三:/pause端点

Spring Boot 应用提供了/pause端点,利用该端点可实现优雅下线。

使用方式:在想下线应用的application.yml中添加配置,从而启用并暴露/pause端点:

management:
  endpoint:
    # 启用pause端点
    pause:
      enabled: true
    # 启用restart端点,之所以要启用restart端点,是因为pause端点的启用依赖restart端点的启用
    restart:
      enabled: true
  endpoints:
    web:
      exposure:
        include: pause,restart

发送 POST 请求到/actuator/pause端点:

curl -X POST http://你想停止的服务实例地址/actuator/pause

执行后的效果类似下图:

如图所示,该应用在 Eureka Server 上的状已被标记为DOWN,但是应用本身其实依然是可以正常对外服务的。在 Spring Cloud 中,Ribbon 做负载均衡时,只会负载到标记为UP的实例上。

利用这两点,你可以:先用/pause端点,将要下线的应用标记为DOWN,但不去真正停止应用;然后过一定的时间(例如 90 秒,或者自己做个监控,看当前实例的流量变成 0 后)再去停止应用,例如kill应用。

缺点 & 局限

方式四:/service-registry端点

使用方式:在想下线应用的application.yml中添加配置,从而暴露/service-registry端点:

management:
  endpoints:
    web:
      exposure:
        include: service-registry

发送 POST 请求到/actuator/service-registry端点:

curl -X "POST" "http://localhost:8000/actuator/service-registry?status=DOWN" \
   -H "Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8"

实行后的效果类似如下图:

图片

优雅的下线方式

在上文中,我们讲述了四种常见的下线方式,对比来看,方式四是一种比较优雅的下线方式。


在实际项目中,我们可以先使用/service-registry端点,将服务标记为DOWN,然后监控服务的流量,当流量为 0 时,即可升级该服务。当然,这里假设我们部署了多个服务实例,当一个服务实例DOWN掉之后,其他服务实例仍然是可以提供服务的,如果就部署一台服务的话,那么讨论优不优雅就没那么重要了。

除了上述的下线方式之外,还有一种利用EurekaAutoServiceRegistration对象达到优雅下线的目标。

  • 执行eurekaAutoServiceRegistration.start()方法时,当前服务向 Eureka 注册中心注册服务;
  • 执行eurekaAutoServiceRegistration.stop()方法时,当前服务会向 Eureka 注册中心进行反注册,注册中心收到请求后,会将此服务从注册列表中删除。

示例代码如下:

@RestController
@RequestMapping(value = "/graceful/registry-service")
public class GracefulOffline {

    @Autowired
    private EurekaAutoServiceRegistration eurekaAutoServiceRegistration;

    @RequestMapping("/online")
    public String online() {
        this.eurekaAutoServiceRegistration.start();
        return "execute online method, online success.";
    }

    @RequestMapping("/offline")
    public String offline() {
        this.eurekaAutoServiceRegistration.stop();
        return "execute offline method, offline success.";
    }
}

到这里,我们已经介绍了两种相对优雅的下线方式了。具体如何操作,我们可以根据实际上情况进行包装,或者利用自动化的脚本来实现更加优雅的下线方式。

灰度发布

蓝绿部署

蓝绿部署,英文名为 Blue Green Deployment,是一种可以保证系统在不间断提供服务的情况下上线的部署方式。

如何保证系统不间断提供服务呢?那就是同时部署两个集群,但仅对外提供一个集群的服务,当需要升级时,切换集群进行升级。蓝绿部署无需停机,并且风险较小。其大致步骤为:

  • 部署集群 1 的应用(初始状态),将所有外部请求的流量都打到这个集群上
  • 部署集群 2 的应用,集群 2 的代码与集群 1 不同,如新功能或者 Bug 修复等
  • 将流量从集群 1 切换到集群 2
  • 如集群 2 测试正常,就删除集群 1 正在使用的资源(例如实例),使用集群 2 对外提供服务

因为在使用蓝绿部署的方式时,我们需要控制流量,所以我们需要借助路由服务,如 Nginx 等。

滚动部署

滚动部署,英文名为 Rolling Update,同样是一种可以保证系统在不间断提供服务的情况下上线的部署方式。和蓝绿部署不同的是,滚动部署对外提供服务的版本并不是非此即彼,而是在更细的粒度下平滑完成版本的升级。

如何做到细粒度平滑升级版本呢?滚动部署只需要一个集群,集群下的不同节点可以独立进行版本升级。比如在一个 12 节点的集群中,我们每次升级 4 个节点,并将升级后的节点重新投入使用,周而复始,直到集群中所有的节点都更新为新版本。

这种部署方式相对于蓝绿部署,更加节约资源,因为它不需要运行两个集群。但这种方式也有很多缺点,例如:

  • 没有一个确定 OK 的环境。使用蓝绿部署,我们能够清晰地知道老版本是 OK 的,而使用滚动发布,我们无法确定。
  • 修改了现有的环境。
  • 如果需要回滚,很困难。举个例子,在某一次发布中,我们需要更新 100 个实例,每次更新 10 个实例,每次部署需要 5 分钟。当滚动发布到第 80 个实例时,发现了问题,需要回滚。这时,我们估计就要疯了。
  • 有的时候,我们还可能对系统进行动态伸缩,如果部署期间,系统自动扩容/缩容了,我们还需判断到底哪个节点使用的是哪个代码。尽管有一些自动化的运维工具,但是依然令人心惊胆战。

并不是说滚动发布不好,滚动发布也有它非常合适的场景。

金丝雀部署

金丝雀部署又称灰度部署(或者,灰度发布),英文名为 Canary Deployment,是指在黑与白之间,能够平滑过渡的一种发布方式


金丝雀的名称来源于「矿井中的金丝雀」,早在 17 世纪,英国矿井工人发现,金丝雀对瓦斯这种气体十分敏感,空气中哪怕有极其微量的瓦斯,金丝雀也会停止歌唱;而当瓦斯含量超过一定限度时,虽然鲁钝的人类毫无察觉,金丝雀却早已毒发身亡。当时在采矿设备相对简陋的条件下,工人们每次下井都会带上一只金丝雀作为“瓦斯检测指标”,以便在危险状况下紧急撤离。


我们来看一下金丝雀部署的步骤:

  • 准备好部署各个阶段的工件,包括:构建工件,测试脚本,配置文件和部署清单文件
  • 从负载均衡列表中移除掉“金丝雀”服务器
  • 升级“金丝雀”应用(切断原有流量并进行部署)
  • 对应用进行自动化测试
  • 将“金丝雀”服务器重新添加到负载均衡列表中(连通性和健康检查)
  • 如果“金丝雀”在线使用测试成功,升级剩余的其他服务器(否则就回滚)


在金丝雀部署中,常常按照用户量设置路由权重,例如 90% 的用户维持使用老版本,10% 的用户尝鲜新版本。不同版本应用共存,经常与 A/B 测试一起使用,用于测试选择多种方案。


金丝雀部署比较典型的例子,就是我们在使用某个应用的时候,该应用邀请我们进行“内测”或者“新版本体验”,如果我们同意了,那么我们就成了金丝雀。

原文

运维常用的34个Linux Shell脚本 对你一定有帮助!
« 上一篇 2022-05-09
做SQL性能优化真的是干瞪眼
下一篇 » 2022-05-11
  • 胡迪核心知识点详解(好文章合集)
    1阅读 0条评论 个赞
    以下文章来源于公众号-3分钟秒懂大数据,作者在IT中穿梭旅行在Flink实时流中,经常会通过FlinkCDC插件读取Mysql数据,然后写入Hudi中。所以在执行上述操作时,需要了解……
  • 前端面试必须解决网络中的跨域问题
    0阅读 0条评论 个赞
    什么是跨域浏览器有一个重要的安全策略,称之为「同源策略」其中,源=协议+主机+端口源=协议+主机+端口源=协议+主机+端口,两个源相同,称之为同源,两个源不同,称之为跨源或跨域比如:源1源2是否同……
  • 如何在Bash脚本中使用强大的Linux测试命令
    0阅读 0条评论 个赞
    Linuxtest命令是Shell内置命令,用来检测某个条件是否成立。test通常和if语句一起使用,并且大部分if语句都依赖test。可以将一个元素与另一个元素进行比较,但它更常……
  • 真正的建筑设计是什么样子的?
    1阅读 0条评论 个赞
    什么是架构和架构本质在软件行业,对于什么是架构,都有很多的争论,每个人都有自己的理解。此君说的架构和彼君理解的架构未必是一回事。因此我们在讨论架构之前,我们先讨论架构的概念定义,概念是人认识这个世界的……
  • 10分钟了解云原生 值得收藏~
    0阅读 0条评论 个赞
    文章转载:奇妙的Linux世界我们已经进入云计算下半场,不再像上半场在纠结要不要上云,而是讨论怎么上云?才能把云计算的价值发挥到淋漓尽致。如何把云计算与不同的业务场景深度结合?如何让技术真正作用于企业……
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
  • Python极简编码规范
    1阅读 0条评论 个赞
    本文是阅读《PythonCodingRule》之后总结的最为精华及简单的编码规范,根据每个人不同喜好有些地方会有不同的选择,我只是做了对自己来说最简单易行的选择,仅供大家参考。1、重要原则a.保持……
  • 高并发服务的几点优化经验
    1阅读 0条评论 个赞
    前言:如何优化高并发服务,这里指的是qps在20万以上的在线服务,注意不是离线服务,在线服务会存在哪些挑战呢?①无法做离线缓存,所有的数据都是实时读的②大量的请求会打到线上服务,对于服务的响应时间要……
  • Redis过期的数据会被立即删除吗?
    1阅读 0条评论 个赞
    本文来源码哥字节(ID:MageByte)❝码哥,当key达到过期时间,Redis就会马上删除么?先说结论:并不会立马删除。Redis有两种删除过期数据的策略:定期选取部分数据删除;惰性删除;……
  • 甲骨文(第11代)单实例-室内空调(第11代)迁移模拟测试
    1阅读 0条评论 个赞
    Oracle11.2.0.4单实例----Oracle19C-RAC迁移模拟测试总体思想:通过RMAN物理备份在备库恢复主库数据,后续通过在主库停业务后,将从备份后的所有日志都同步到新库应用,重新配置……
  • 一行Python代码实现并行
    1阅读 0条评论 个赞
    译者:caspar译文:http://985.so/amks原文:http://985.so/amk5Python在程序并行化方面多少有些声名狼藉。撇开技术上的问题,例如线程的实现和GIL,我……
  • Linux预定任务调度(crontab) 好实用!
    0阅读 0条评论 个赞
    概述crontab命令用于设置周期性被执行的指令。该命令从标准输入设备读取指令,并将其存放于“crontab”文件中,以供之后读取和执行。可以使用crontab定时处理离线任务,比如每天凌晨2点更新数……
  • MySQL查询语句的准备阶段是什么?
    1阅读 0条评论 个赞
    以下文章来源于公众号--一树一溪,作者一树一溪这一篇主要讲的内容是一条简单查询语句,在查询准备阶段会干哪些事情?分3个部分:打开表select*替换为表字段填充where条件示例表及SQ……
  • 7 种提升Spring Boot吞吐量神技!
    0阅读 0条评论 个赞
    一、异步执行实现方式二种:1.使用异步注解@aysnc、启动类:添加@EnableAsync注解2.JDK8本身有一个非常好用的Future类——CompletableFuture@AllArg……
  • 如何正确计算Kubernetes容器的CPU利用率
    1阅读 0条评论 个赞
    本文转自博客园,原文:https://www.cnblogs.com/apink/p/15767687.html,版权归原作者所有。参数解释使用Prometheus配置kubernetes环境……
  • Docker 从入门到实战 未雨绸缪收藏~
    1阅读 0条评论 个赞
    一、概述1.1基本概念Docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议开源。Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中……
  • SQL中的三种重复数据删除方法 还有谁不行?
    1阅读 0条评论 个赞
    SQL去重是数据分析工作中比较常见的一个场景,今天给大家具体介绍3种去重的方法。在使用SQL提数的时候,常会遇到表内有重复值的时候,比如我们想得到uv(独立访客),就需要做去重。在MySQL中……
  • Java处理异常的9个最佳实践 你做得对吗?
    1阅读 0条评论 个赞
    原文:https://dzone.com/articles/9-best-practices-to-handle-exceptions-in-java译者:飒然Hang译文:http://www.r……
  • 关于数据中心最强科普 一个就给你完整了解!
    1阅读 0条评论 个赞
    数据中心,英文缩写叫IDC,也就是InternetDataCenter(互联网数据中心)。之所以不太直接称之为“DC”,主要是为了避免和直流电(DirectCurrent)混淆。而且,现在的数……
  • 3种方式!转到错误处理最佳实践
    1阅读 0条评论 个赞
    以下文章来源于公众号-云加社区,作者李森林导语|错误处理一直以一是编程必需要面对的问题,错误处理如果做的好的话,代码的稳定性会很好。不同的语言有不同的出现处理的方式。Go语言也一样,在本篇文章中,我们……
  • 紧急情况下数据库表被锁 抓瞎?
    4阅读 0条评论 个赞
    以下文章来源于公众号-程序新视界,作者二师兄在程序员的职业生涯中,总会遇到数据库表被锁的情况,前些天就又撞见一次。由于业务突发需求,各个部门都在批量操作、导出数据,而数据库又未做读写分离,结果就是:数……
  • 大数据平台核心架构图解 推荐收藏!
    1阅读 0条评论 个赞
    我们先来看看这张图,这是某公司使用的大数据平台架构图,大部分公司应该都差不多:从这张大数据的整体架构图上看来,大数据的核心层应该是:数据采集层、数据存储与分析层、数据共享层、数据应用层,可能叫法有所不……
  • 阿帕奇建筑师遵循的30条设计原则
    0阅读 0条评论 个赞
    作者介绍Srinath,科学家,软件架构师。ApacheAxis2项目的联合创始人,ApacheSoftware基金会的成员,WSO2流处理器(wso2.com/analytics)的联席架构师。……
  • MySQL批量插入数据 一次插入多少行数据效率最高?
    7阅读 0条评论 个赞
    一、前言我们在操作大型数据表或者日志文件的时候经常会需要写入数据到数据库,那么最合适的方案就是数据库的批量插入。只是我们在执行批量操作的时候,一次插入多少数据才合适呢?假如需要插入的数据有百万条,那……
  • 如何在Linux下扩展XFS根分区
    2阅读 0条评论 个赞
    在某些情况下,/分区在Linux中磁盘空间不足。即使压缩和删除旧的日志文件也无济于事,因此在这种情况下,我们别无选择,只能扩展/文件系统。在本文中,我们将演示如何在Linux系统中扩展不……
  • 内存数据库如何利用内存?
    1阅读 0条评论 个赞
    与以磁盘存储为主的普通数据库相比,内存数据库的数据访问速度可以高出几个数量级,能大幅提高运算性能,更适合高并发、低延时的业务场景。不过,当前大部分内存数据库仍然采用SQL模型,而SQL缺乏一些……
最近发布资讯
更多