爱奇艺基于SpringCloud的韧性能力建设(就近路由策略+优雅上线+优雅下线)
国际站后端业务不断扩展,支撑的服务实例规模也越来越大。并且在此过程中,支持了双云及多地部署。
这也给服务治理带来了挑战,如何应对同城多机房路由、多地容灾等场景,并解决微服务优雅上下线等问题,是国际站业务拓展亟需解决的课题。
本文将从设计、开发、实践各个维度,叙述爱奇艺解决上述问题的思路和实践。
客户端路由
SpringCloud客户端路由
客户端就近路由
什么是就近路由?在业务多机房部署场景中,内部服务如果存在大量的跨机房、甚至跨地域的网络调用,则请求时延会显著加大,会直接影响到服务质量,甚至是用户体验。
但是在一般的微服务架构中,路由策略并不支持这种机房或者地区的多级别判断。所以实现自定义的客户端负载均衡路由变得迫在眉睫。
在常规单机房部署的时候,如下图中的dc1中,consumer只会请求到provider1,整个链路并没有什么问题。但是当需要多机房多区域部署的时候,瓶颈就出现了。假设有下图的简单部署场景:
- provider分别部署在同zone的dc1、同region的dc2和不同region的dc3
- 各自注册到所在dc的注册中心
可以预想到会有以下几个问题:
- 如果consumer能从注册中心获取到所有provider列表,那么它会轮询请求,这样正常情况下就会跨机房访问
- 如果consumer不能从注册中心获取到provider2和provider3,那么在容灾情况下,provider1挂了,不能故障转移到provider1和provider2
这里就有了智能路由的概念,也就是就近路由,如何满足需求呢?需要做到以下几点:
- 各consumer能获取到其他dc的实例列表,也就是注册中心需要支持多dc
- 正常情况下,consumer的流量只会请求到同dc的provider1(通道1),而不会跨机房访问
- 当同dc的provider出现不可用情况下,会首先降级到不同dc但是同region的provider2(通道2),如果provider2也不可用,才会降级到不同region的provider3(通道3)
在讨论实现之前,先同步一下我们后面要用到的idc、zone及region的概念。
- idc、zone及region
这里先给出 AWS 的 Region 和 AZ 示意图,如下:
AZ – Availability Zone 内部保证<1ms,一个机房或多个机房组成
Region 内部之间保证2-5ms时延,多个AZ组成
Region 之间通常20-100ms,取决于物理距离
SpringCloud现有能力
Netflix Ribbon
Ribbon是一个为客户端提供负载均衡功能的服务,它内部提供了一个叫做ILoadBalance的接口代表负载均衡器的操作,比如有添加服务器操作、选择服务器操作、获取所有的服务器列表、获取可用的服务器列表等等。
以下就是Ribbon提供的负载均衡规则列表:
可以看到,Ribbon是提供了基于zone的ZoneAvoidanceRule,它可以根据zone进行服务选择。但是如果有region等概念,它就没办法处理了。
Spring Cloud Loadbalancer
Spring Cloud在新版本中,逐渐抛弃Netflix的内容,比如ribbon。也确实是ribbon已经停止更新很久了。重新推出的Spring Cloud LoadBalancer只有简单的轮询和随机路由策略。在新的版本中,也在新增按照时间权重等等策略。
它主要是支持了响应式的服务选择,像ribbon的服务选择还是同步的,这与Spring Cloud 在倡导的响应式趋势不符。
可以看到新版本的Load Balancer支持的路由功能还很初级,也并不支持微服务高可用方方案下的智能就近路由。
自定义扩展能力
经过对Spring Cloud现有能力的调研和期望需求的评估,决定对Spring Cloud进行自定义扩展,支持就近路由的功能,并期望在短期内服务公司内部开源,未来贡献给开源社区。
经过和架构组同学的讨论和之前dubbo就近路由的扩展经验,设计了以下功能改动:
可以看到,大体分为以下几步:
- provider注册时,调用服务获取自身所在的zone和region,并且向注册中心注册时携带zone和region信息
- consumer启动时也调用服务获取自身所在的zone和region
- consumer在拉取实例时,首先筛选同zone的实例
- 如果同zone实例中健康比例大于50%,则进行负载均衡策略选择一台实例
- 如果同zone中健康比例小于50%,则降级到同region中进行判断,逻辑同上
- 最后如果还未筛选出足够数量的实例,则降级到返回所有实例。然后进行负载均衡策略选择
经过路由策略改造后,客户端负载均衡具备了就近路由的功能,基本具备容灾降级的能力。
国际站落地案例
国际站在爱奇艺海外机房接入自定义扩展的spring-cloud-iqiyi后。把服务进行部署演练大致情况如下:
期望结果
- 正常三个dc都健康时,流量是通道
- 当dc1的服务被摘除,流量是通道
- 当dc1和dc2的服务都被摘除,流量是通道
演练步骤
- 使用Hoxton.SR11-iqiyi-0.1.1版本的spring-cloud-iqiyi
- 针对JAVA类型应用,对容器进行杀死演练
结果展示
从演练结果看,符合预期。进行了常规情况下就近路由,异常情况下的智能路由
优雅上下线
SpringCloud优雅上下线
在部署和实践SpringCloud服务过程中,发现在服务部署过程中,总有接口超时或者接口5xx的情况。分析后发现原因有以下两点:
- 新启动的实例没有进行预热或者预热没有执行完,流量就进入,导致接口请求超时
- kill的实例,在退出后,还有consumer的流量进入,导致出现接口5xx
其实这是微服务架构中的常见问题,即如何进行预热以及优雅上下线。具体应该如何处理?
假如有这样的简单的微服务架构:
在微服务架构体系中,理想的优雅上下线过程应该是像下面这样:
provider1就是对应的优雅下线,provider2就是对应的优雅上线。而且顺序不能颠倒。
在Spring Cloud的体系中,使用consul、ribbon等组件下,总结下优雅上下线就是:
SpringCloud优雅上线
自定义扩展能力
针对SpringCloud现有架构,我们在SpringBoot启动过程中,改变之前服务注册的时机,延迟注册并保证服务预热。
通过禁用SpringBoot原生在WebServerIntializedEvent事件监听器中实现的自动注册功能,改为在ApplicationReadyEvent事件监听器中实现自定义的自动注册,实现了延迟注册和执行自定义预热逻辑的能力。
当然自定义预热逻辑可以由业务代码控制,可以根据实际项目中的需求,进行本地缓存预热、长连接预热、连接池预热等。
同步执行完预热后,再进行服务注册,注册完成后才会收到consumer请求,避免由于冷启动造成的慢请求。
SpringCloud优雅下线
自定义扩展能力
针对SpringCloud现有架构,我们在SpringBoot退出过程中,增加自定义逻辑,保证服务下线过程中严格按照上面的流程。
具体如上图所示,在ContextClosedEvent事件中,拦截处理。首先执行解注册,这个时候注册中心已经没有当前provider。
然后等待一段时间(可配置),直到consumer的serverList更新(ribbon默认是30s),再继续执行退出流程。
Spring Boot优雅退出
上面我们介绍了微服务架构中的优雅上下线,但是在服务本身,也存在优雅停机的问题。
什么叫优雅停机?简单说就是,在对应用进程发送停止指令之后,能保证正在执行的业务操作不受影响。应用接收到停止指令之后的步骤应该是,停止接收访问请求,等待已经接收到的请求处理完成,并能成功返回,这时才真正停止应用。
这种完美的应用停止方式如何实现呢?Java语言本身是支持优雅停机的,当我们使用kill PID的方式结束一个Java应用的时候,JVM会收到一个停止信号,然后执行shutdownHook的线程。
Spring Boot现有能力
SpringBoot 2.3.0开始提供了官方的优雅停机方案,那我们首先来看下需要怎么使用呢?首先需要在配置文件中配置优雅停机,如下:
server:
shutdown: graceful ## 开启优雅停机
spring:
lifecycle:
timeout-per-shutdown-phase: 5s ## 优雅停机等待时间,默认30s
而在Spring Boot 2.3以前,是没有官方方案的,需要自己实现shutdownhook,具体参考官方的issue。大体步骤就是判断是否为tomcat的线程,如果是则等待线程状态完成再关闭。
所以,一般建议直接升级到Spring Boot 2.3,使用新特性。
成果
经过一系列的自定义扩展,SpringCloud已完善大多比较重要的功能,基于现有扩展功能,国际站完成部署两地三中心架构:
后端服务整体稳定性得到大大提升,并且具备很强的容灾能力。
还有一些比如标签路由、灰度部署等扩展功能,也亟待开发解决。未来,我们也计划将这些扩展开源贡献给SpringCloud社区,共同进步!
本文来自 爱奇艺技术产品团队
近期,123云盘开始限制,必须注册帐号且登录后才能下载,且限制每天下载流量1GB,下载 123云盘免流量破解工具
版权声明:
小编:牛A与牛C之间
链接:https://wuleba.com/1057.html
来源:吾乐吧软件站
本站资源仅供个人学习交流,请于下载后 24 小时内删除,不允许用于商业用途,否则法律问题自行承担。
下载说明:请不要相信网盘那边的广告,不要下载APP,普通下载就完事了!
共有 0 条评论