前言
在生产环境中,如何保障在服务降级的时候,不影响用户的体验,这个是一个十分重要的问题。如果在咱们降级服务的时候,会造成一段时间内的服务不可用,这就是不够优雅的。那什么是优雅的呢?次要就是指在服务降级的时候,不中断整个服务,让用户无感知,进而不会影响用户的体验,这就是优雅的。
实际上,优雅下线是指标,而不是伎俩,它是一个绝对的概念,例如 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
端点,能够借助它实现优雅停机。
应用形式:在想下线利用的 application.yml 中增加如下配置,从而启用并裸露 /shutdown
端点:
management:
endpoint:
shutdown:
enabled: true
endpoints:
web:
exposure:
include: shutdown
发送 POST 申请到 /shutdown 端点
curl -X http:// 你想进行的服务地址 /actuator/shutdown
该形式实质和形式一是一样的,也是借助 Spring Boot 利用的 Shutdown hook 去实现的。
Spring Boot 根底就不介绍了,举荐看这个收费教程:
https://github.com/javastacks/spring-boot-best-practice
形式三:/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 测试一起应用,用于测试抉择多种计划。
金丝雀部署比拟典型的例子,就是咱们在应用某个利用的时候,该利用邀请咱们进行“内测”或者“新版本体验”,如果咱们批准了,那么咱们就成了金丝雀。
版权申明:本文为 CSDN 博主「CG 国斌」的原创文章,遵循 CC 4.0 BY-SA 版权协定,转载请附上原文出处链接及本申明。原文链接:https://blog.csdn.net/qq_3524…
近期热文举荐:
1.1,000+ 道 Java 面试题及答案整顿(2022 最新版)
2. 劲爆!Java 协程要来了。。。
3.Spring Boot 2.x 教程,太全了!
4. 别再写满屏的爆爆爆炸类了,试试装璜器模式,这才是优雅的形式!!
5.《Java 开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞 + 转发哦!