前言
在生产环境中,如何保证在服务升级的时候,不影响用户的体验,这个是一个非常重要的问题。如果在我们升级服务的时候,会造成一段时间内的服务不可用,这就是不够优雅的。那什么是优雅的呢?主要就是指在服务升级的时候,不中断整个服务,让用户无感知,进而不会影响用户的体验,这就是优雅的。
实际上,优雅下线是目标,而不是手段,它是一个相对的概念,例如kill PID和kill -9 PID都是暴力杀死服务,相对于kill -9 PID来说,kill PID就是优雅的。但如果单独拿kill PID出来说,我们能说它是优雅的下线策略吗?肯定不是啊,就是这个道理。
因此,本文讲述的优雅下线仅能称之为“相对的优雅下线”,但相对于暴力的杀死服务,已经足够优雅了。常见的优雅解决方案,主要包括优雅下线和灰度发布。而实际上,灰度发布的范围就已经包含优雅下线了。最后,在本文中,我们主要讲述基于 Spring Cloud 和 Euraka 的优雅下线以及灰度发布。
优雅下线
常见的下线方式
方式一:kill PID
使用方式:kill java进程ID
该方式借助的是 Spring Boot 应用的 Shutdown hook,应用本身的下线也是优雅的,但如果你的服务发现组件使用的是 Eureka,那么默认最长会有 90 秒的延迟,其他应用才会感知到该服务下线,这意味着:该实例下线后的 90 秒内,其他服务仍然可能调用到这个已下线的实例。因此,该方式是不够优雅的 。
方式二:/shutdown端点
Spring Boot 提供了/shutdown端点,可以借助它实现优雅停机。
使用方式:在想下线应用的applicationyml中添加如下配置,从而启用并暴露/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应用。
缺点 & 局限
缺点 | 描述 |
---|---|
不同的版本配置不大一样 | 早期的 Spring Cloud 版本中,pause端点是不依赖restart端点的 |
无法和 Eureka 的健康检查配合使用 | 如果你的服务发现组件用的是 Eureka,并且你的应用开启了健康检查eureka.client.healthcheck.enabled = true,那么/pause端点无效 |
方式四:/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对象达到优雅下线的目标。
示例代码如下:
@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,是一种可以保证系统在不间断提供服务的情况下上线的部署方式。
如何保证系统不间断提供服务呢?那就是同时部署两个集群,但仅对外提供一个集群的服务,当需要升级时,切换集群进行升级。蓝绿部署无需停机,并且风险较小。其大致步骤为:
因为在使用蓝绿部署的方式时,我们需要控制流量,所以我们需要借助路由服务,如 Nginx 等。
滚动部署
滚动部署,英文名为 Rolling Update,同样是一种可以保证系统在不间断提供服务的情况下上线的部署方式。和蓝绿部署不同的是,滚动部署对外提供服务的版本并不是非此即彼,而是在更细的粒度下平滑完成版本的升级。
如何做到细粒度平滑升级版本呢?滚动部署只需要一个集群,集群下的不同节点可以独立进行版本升级。比如在一个 12 节点的集群中,我们每次升级 4 个节点,并将升级后的节点重新投入使用,周而复始,直到集群中所有的节点都更新为新版本。
这种部署方式相对于蓝绿部署,更加节约资源,因为它不需要运行两个集群。但这种方式也有很多缺点,例如:
并不是说滚动发布不好,滚动发布也有它非常合适的场景。
金丝雀部署
金丝雀部署又称灰度部署(或者,灰度发布),英文名为 Canary Deployment,是指在黑与白之间,能够平滑过渡的一种发布方式。
金丝雀的名称来源于「矿井中的金丝雀」,早在 17 世纪,英国矿井工人发现,金丝雀对瓦斯这种气体十分敏感,空气中哪怕有极其微量的瓦斯,金丝雀也会停止歌唱;而当瓦斯含量超过一定限度时,虽然鲁钝的人类毫无察觉,金丝雀却早已毒发身亡。当时在采矿设备相对简陋的条件下,工人们每次下井都会带上一只金丝雀作为“瓦斯检测指标”,以便在危险状况下紧急撤离。
我们来看一下金丝雀部署的步骤:
在金丝雀部署中,常常按照用户量设置路由权重,例如 90% 的用户维持使用老版本,10% 的用户尝鲜新版本。不同版本应用共存,经常与 A/B 测试一起使用,用于测试选择多种方案。金丝雀部署比较典型的例子,就是我们在使用某个应用的时候,该应用邀请我们进行“内测”或者“新版本体验”,如果我们同意了,那么我们就成了金丝雀。
参考资料:
实用技巧:Spring Cloud中,如何优雅下线微服务?
Spring cloud系列20 实现服务优雅上下线
Spring Cloud 灰度发布解决方案
一文搞懂蓝绿部署和金丝雀发布
微服务部署:蓝绿部署、滚动部署、灰度发布、金丝雀发布
到此这篇关于Spring Cloud 优雅下线以及灰度发布实现的文章就介绍到这了,更多相关Spring Cloud 优雅下线及灰度发布内容请搜索小牛知识库以前的文章或继续浏览下面的相关文章希望大家以后多多支持小牛知识库!
对于灰度发布,这里主要讲解如何实现,我所在的公司虽然使用这个逻辑实现的. 但是由于掺杂了太多业务相关东西,比如抓包,限流,缓存,校验,sso,云化,监控告警,成为了一个运维平台. 造成无法开源,真是好可惜.做这个系统多年还是想让大家来找找茬刷刷存在感的 我想当前没有一个开源的可能也和这个原因有关,太多功能和业务相关难以抽离成纯粹组件开源. 下面先讲主要逻辑结构,请看下图 这里需要讲解下这里面几个名
从1.14.0开始支持预发布、灰度发布,可登陆SOP-Admin,然后选择服务列表进行操作。 使用预发布 SOP中预发布的思路如下: 假设网关工程sop-gateway在阿里云负载均衡有两台服务器,域名分别为: 域名 说明 open1.domain.com 网关服务器1 openpre.domain.com 网关服务器2,作为预发布请求入口 SLB对外域名为:open.domain.com,即开放
1. 功能介绍 你可以点击 这里 查看灰度发布功能的介绍信息。 2. 常见问题 2.1 设置方案生效方式后,为什么无法编辑发布规则? 在设置了方案生效方式后,【发布规则】中的添加按钮将无法使用,如下图所示。此时,开发者将无法: 删除已经导入的用户列表 删除已经选择的其他规则 添加新的其他规则 此时,如需更改规则,则需要删除已经配置好的【发布规则】,此时就可以继续编辑发布规则。 2.2 范围内/范围
1. 功能演示 FinClip 特别为您制作了灰度发布功能的介绍与功能操作演示视频,您可以点击这里 (opens new window)查看演示视频。 在本视频中,主要帮助您介绍如下内容: 什么是灰度发布 了解灰度发布功能、面向的业务场景 了解如何在App中实现一个真实的、“千人千面”的业务目标 如何进行灰度发布的规则配置 了解如何创建企业的自有规则库 了解规则配置页面功能 如何创建灰度发布 了解
SOP网关采用自定义负载均衡策略来实现对预发布/灰度发布服务器实例的选择。 spring cloud gateway默认的负载均衡实现类在:org.springframework.cloud.gateway.filter.LoadBalancerClientFilter.java中 这个类主要做了几件事情: 解析出请求路径中的scheme 如果scheme不是以lb协议开头直接跳过 如果schem
中型的互联网公司往往有着以百万计的用户,而大型互联网公司的系统则可能要服务千万级甚至亿级的用户需求。大型系统的请求流入往往是源源不断的,任何风吹草动,都一定会有最终用户感受得到。例如你的系统在上线途中会拒绝一些上游过来的请求,而这时候依赖你的系统没有做任何容错,那么这个错误就会一直向上抛出,直到触达最终用户。形成一次对用户切切实实的伤害。这种伤害可能是在用户的APP上弹出一个让用户摸不着头脑的诡异