爱奇艺基于SpringCloud的韧性能力建设
国际站后端业务不断扩展,支撑的服务实例规模也越来越大。并且在此过程中,支持了双云及多地部署。
这也给服务治理带来了挑战,如何应对同城多机房路由、多地容灾等场景,并解决微服务优雅上下线等问题,是国际站业务拓展亟需解决的课题。
本文将从设计、开发、实践各个维度,叙述爱奇艺解决上述问题的思路和实践。
01
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都健康时,流量是通道1
当dc1的服务被摘除,流量是通道2
当dc1和dc2的服务都被摘除,流量是通道3
演练步骤
使用Hoxton.SR11-iqiyi-0.1.1版本的spring-cloud-iqiyi
针对JAVA类型应用,对容器进行杀死演练
结果展示
从演练结果看,符合预期。进行了常规情况下就近路由,异常情况下的智能路由
02
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,使用新特性。
03
成果
经过一系列的自定义扩展,SpringCloud已完善大多比较重要的功能,基于现有扩展功能,国际站完成部署两地三中心架构:
后端服务整体稳定性得到大大提升,并且具备很强的容灾能力。
还有一些比如标签路由、灰度部署等扩展功能,也亟待开发解决。未来,我们也计划将这些扩展开源贡献给SpringCloud社区,共同进步!
爱奇艺基于SpringCloud的韧性能力建设相关推荐
- 爱奇艺基于 Docker 的 App Engine 实践
杨成伟:大家好,我是来自爱奇艺的杨成伟,现在在爱奇艺公司内部负责弹性计算云方面的建设,之前我是做移动操作系统的,之前在因特尔做MeeGo和Python,有几年的经验,主要是在操作系统的核心层,但是是在 ...
- 爱奇艺基于 Vue 的微前端架构实践
点击上方"开发者技术前线",选择"星标" 18:50 在看 真爱 来自:爱奇艺技术产品团队 前言 近来,微前端的概念非常火爆,那么什么是微前端架构?微前端架构是 ...
- 爱奇艺大数据实时分析平台的建设与实践
0 导语 生活在信息爆炸时代的我们越来越清晰的认识到海量信息与数据分析的重要性,如提高数据挖掘能力.为运营决策提供关键数据.通过数据分析助力业务创新.在商业决策中的提供较有价值的信息等成为关键,于是大 ...
- 爱奇艺抢跑影视工业化 继续“押注”好内容
北京时间5月18日,百度.爱奇艺.网易等巨头相继发布新一季度业绩.从财报发布后的股价表现来看,三家公司均有不同幅度的上涨,其中爱奇艺因一季度财报超预期,当天股价大涨10%. 在财报超市场预期背后,我们 ...
- 基于 Apache Druid 的实时分析平台在爱奇艺的实践
- 导读 - 最近几年大数据技术在各行各业得到广泛应用,为企业的运营决策和各种业务提供支持.随着数据的增长,业务对数据时效性的要求,给企业的大数据分析带来了巨大挑战.针对海量数据的实时分析需求,近年来 ...
- 基于Apache Flink的爱奇艺实时计算平台建设实践
导读:随着大数据的快速发展,行业大数据服务越来越重要.同时,对大数据实时计算的要求也越来越高.今天会和大家分享下爱奇艺基于Apache Flink的实时计算平台建设实践. 今天的介绍会围绕下面三点展开 ...
- Flink从入门到精通100篇(二十三)-基于Apache Flink的爱奇艺实时计算平台建设实践
前言 随着大数据的快速发展,行业大数据服务越来越重要.同时,对大数据实时计算的要求也越来越高.今天会和大家分享下爱奇艺基于Apache Flink的实时计算平台建设实践. 今天的介绍会围绕下面三点展开 ...
- 爱奇艺大数据生态的实时化建设
简介:实时化是大数据未来最重要的方向之一. 作者|爱奇艺大数据团队 数据作为互联网时代的基础生产资料,在各大公司企业拥有举足轻重的地位.数据的价值在互联网公司的体现,大致而言可以分成三类: 发掘数据中 ...
- 从 Spark Streaming 到 Apache Flink : 实时数据流在爱奇艺的演进
作者:陈越晨 整理:刘河 本文将为大家介绍Apache Flink在爱奇艺的生产与实践过程.你可以借此了解到爱奇艺引入Apache Flink的背景与挑战,以及平台构建化流程.主要内容如下: 爱奇艺在 ...
最新文章
- Pjax是什么以及为什么推荐大家用
- 深入浅出CMake(二): 基础语法
- Oracle服务扫描工具Oscanner
- go build和go install的区别
- #react-native BUG#
- 安装jenkins时出现 No such plugin: cloudbees-folder的解决办法
- 理论与实践:不要过度思考
- scrapy抓取淘宝女郎
- c++ mysql 配置文件_C++操作数据库写入到json配置文件中
- android动画能超过父容器吗,Android中你不得不知道的动画知识 (一)
- 310. 最小高度树
- 深入String 与StringBuffer详解那个更省资源
- 1. VS2017社区版安装
- dwg格式的计算机图,dwg是什么文件 怎么打开【图文】
- qpython3h_QPython3H安卓运行Python神器
- 32位操作系统电脑上的打印机如何共享给64位操作系统的电脑想要使用_hudingyin_新浪博客
- win10从网络访问计算机没有guest,简单几步解决win10没有权限访问网络资源的问题...
- 计算机count是什么函数,2010年职称计算机考试:计数函数COUNT
- RabbitMQ的消息补偿机制
- A. Omkar and Bad Story
热门文章
- oracle9i的全局变量,Oracle9i, 10g 如何抓取绑定变量的值
- php如何操作文本框,php如何清除文本框
- docker中安装mycat
- 企业IT运维的“安全终结者”-堡垒机指南
- android 代码获取图片信息吗,Android 通过网络获取图片的代码
- [kuangbin带你飞]专题七线段树 更新ing
- 思维dp ---- 复杂状态找中间状态作为dp状态 1552F - Telepanting
- 主席树 ---- CodeForces - 813E(主席树,固定一端去考虑情况)
- BZOJ 2131 免费的馅饼(DP,二维偏序问题 / 旋转坐标轴转化问题)【BZOJ 修复工程】
- 使最新版Code::Blocks支持C++11标准