解决微服务架构下流量有损问题的实践和探索

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 绝⼤多数的软件应⽤⽣产安全事故发⽣在应⽤上下线发布阶段,尽管通过遵守业界约定俗成的可灰度、可观测和可滚回的安全⽣产三板斧,可以最⼤限度的规避发布过程中由于应⽤⾃身代码问题对⽤户造成的影响。但对于⾼并发⼤流量情况下的短时间流量有损问题却仍然⽆法解决。因此,本文将围绕发布过程中如何解决流量有损问题实现应⽤发布过程中的⽆损上下线效果相关内容展开⽅案介绍。

image.png

作者 | 铖朴
来源 | 阿里开发者公众号

绝⼤多数的软件应⽤⽣产安全事故发⽣在应⽤上下线发布阶段,尽管通过遵守业界约定俗成的可灰度、可观测和可滚回的安全⽣产三板斧,可以最⼤限度的规避发布过程中由于应⽤⾃身代码问题对⽤户造成的影响。但对于⾼并发⼤流量情况下的短时间流量有损问题却仍然⽆法解决。因此,本文将围绕发布过程中如何解决流量有损问题实现应⽤发布过程中的⽆损上下线效果相关内容展开⽅案介绍。

无损上下线背景

据统计,应⽤的事故⼤多发⽣在应⽤上下线过程中,有时是应⽤本身代码问题导致。但有时我们也会发现尽管代码本身没有问题,但在应⽤上下线发布过程中仍然会出现短时间的服务调⽤报错,⽐如调⽤时出现Connection refused和No instance等现象。相关问题的原因有相关发布经历的同学或多或少可能有⼀定了解,⽽且⼤家发现该类问题⼀般在流量⾼峰时刻尤为明显,半夜流量少的时候就⽐较少见,于是很多⼈便选择半夜三更进⾏应⽤发布希望以此来规避线上发布事故。本节将就这些问题出现的背后真实原因以及业界对应的设计⽅案展开介绍。常见的流量有损现象出现的原因包括但不限于以下⼏种:

  • 服务⽆法及时下线:服务消费者感知注册中⼼服务列表存在延时,导致应⽤特定实例下线后在⼀段时间内服务消费者仍然调⽤已下线实例造成请求报错。
  • 初始化慢:应⽤刚启动接收线上流量进⾏资源初始化加载,由于流量太⼤,初始化过程慢,出现⼤量请求响应超时、阻塞、资源耗尽从⽽造成刚启动应⽤宕机。
  • 注册太早:服务存在异步资源加载问题,当服务还未初始化完全就被注册到注册中⼼,导致调⽤时资源未加载完毕出现请求响应慢、调⽤超时报错等现象。
  • 发布态与运⾏态未对⻬:使⽤Kubernetes的滚动发布功能进⾏应⽤发布,由于Kubernetes的滚动发布⼀般关联的就绪检查机制,是通过检查应⽤特定端⼝是否启动作为应⽤就绪的标志来触发下⼀批次的实例发布,但在微服务应⽤中只有当应⽤完成了服务注册才可对外提供服务调⽤。因此某些情况下会出现新应⽤还未注册到注册中⼼,⽼应⽤实例就被下线,导致⽆服务可⽤。

接下来,将就具体的下线和上线过程中如何避免流量损耗问题进⾏分别介绍。

无损下线

由于微服务应用自身调用特点,在高并发下,服务提供端应用实例的直接下线,会导致服务消费端应用实例无法实时感知下游实例的实时状态因而出现继续将请求转发到已下线的实例从而出现请求报错,流量有损。

image.png

图1 Spring Cloud应⽤消费者⽆法及时感知提供者服务下线

例如对于Spring Cloud应⽤如上图1所示,当应⽤的两个实例A’和A中的A下线时,由于
Spring Cloud框架为了在可⽤性和性能⽅⾯做平衡,消费者默认是30s去注册中⼼拉取最新的服务列表,因此A实例的下线不能被实时感知,流量较⼤时,消费者会继续通过本地缓存调⽤已下线的A实例导致出现流量有损。基于上述背景,业界提出了相应的⽆损下线(也叫优雅下线)的技术⽅案来应对上述问题。本节将对业界主流的⼀些⽆损下线技术⽅案进⾏介绍。

针对该类问题,业界一般的解决方式是通过将应用更新流程划分为手工摘流量、停应用、更新重启三个步骤。由人工操作实现客户端避免调用已下线实例,这种方式简单而有效,但是限制较多:不仅需要借助流控能力来实现实时摘流量,还需要在停应用前人工判断来保证在途请求已经处理完毕。这种需要人工介入的方式运维复杂度较高,只适用于规模较小的应用,无法解决当前云原生架构下,自动化的弹性伸缩、滚动升级等场景中的实例下线过程中的流量有损问题。本节将对业界应用于云原生场景中的一些无损下线技术方案进行介绍。

1 主动通知

一般注册中心都提供了主动注销接口供微服务应用正常关闭时调用,以便下线实例能及时更新其在注册中心上的状态。主动注销在部分基于事件感知注册中心服务列表的微服务框架比如Dubbo中能及时让上游服务消费者感知到提供者下线避免后续调用已下线实例。但对于像Spring Cloud这类微服务框架服务消费者感知注册中心实例变化是通过定时拉取服务列表的方式实现。尽管下线实例通过注册中心主动注销接口更新了其自身在注册中心上的应用状态信息但由于上游消费者需要在下一次拉取注册中心应用列表时才能感知到,因此会出现消费者感知注册中心实例变化存在延时。在流量较大、并发较高的场景中,当实例下线后,仍无法实现流量无损。既然无法通过注册中心让存量消费者实例实时感知下游服务提供者的变化情况,业界提出了利用主动通知解决该类问题。主动通知过程如下图2所示:

image.png

图2 ⽆损下线⽅案

如图2所示,服务提供者B中某个实例在下线时为避免主动在注册中心中注销的服务实例状态无法实时被上游消费者A感知到,从而导致调用已下线实例的问题。在接收到下线命令即将下线前,提供者B对于在等待下线阶段内收到的请求,在其返回值中都增加上特殊标记让服务消费者接收到返回值并识别到相关标志后主动拉取一次注册中心服务实例从而实时感知B实例最新状态,从而达到服务提供者的下线状态能够被服务消费者实时感知。

2 自适应等待

在并发度不⾼的场景下,主动通知⽅法可以解决绝⼤部分应⽤下线流量有损问题。但对于⾼并发⼤流量应⽤下线场景,如果主动通知完,可能仍然存在⼀些在途请求需要待下线应⽤处理完才能下线否则这些流量就⽆法正常被响应。为解决该类在途请求问题,可通过给待下线应⽤在下线前通过⾃适应等待机制在处理完所有在途请求后,再下线以实现流量⽆损。

image.png

图3 ⾃适应等待机制

如上图3所示,⾃适应等待机制是通过待下线应⽤统计应⽤中是否仍然存在未处理完的在途请求,来决定应⽤下线的时机,从⽽让待下线应⽤在下线前处理完所有剩余请求。

无损上线

延迟加载是软件框架设计过程中最常⻅的⼀种策略,例如在Spring Cloud框架中Ribbon组件的拉取服务列表初始化默认都是要等到服务的第⼀次调⽤时刻,例如下图4是Spring Cloud应⽤中第⼀次和第⼆次通过调⽤RestTemplate调⽤远程服务的耗时对比情况:

image.png

图4 应⽤启动资源初始化与正常运⾏过程中耗时情况对⽐

由图4结果可⻅,第⼀次调⽤由于进⾏了⼀些资源初始化,耗时是正常情况的数倍之多。因此把新应⽤发布到线上直接处理⼤流量极易出现⼤量请求响应慢,资源阻塞,应⽤实例宕机的现象。

业界针对上述应⽤⽆损上线场景提出如下包括延迟注册、⼩流量服务预热以及就绪检查等⼀系列解决⽅案,详细完整的⽅案如下图5所示:

image.png

图5 ⽆损上线整体⽅案

1 延迟注册

对于初始化过程需要异步加载资源的复杂应⽤启动过程,由于注册通常与应⽤初始化过程同步进⾏,从⽽出现应⽤还未完全初始化就已经被注册到注册中⼼供外部消费者调⽤,此时直接调⽤由于资源未加载完成可能会导致请求报错。通过设置延迟注册,可让应⽤在充分初始化后再注册到注册中⼼对外提供服务。例如开源微服务治理框架Dubbo原⽣就提供延迟注册功能[1]。

2 小流量服务预热

在线上发布场景下,很多时候刚启动的冷系统直接处理⼤量请求,可能由于系统内部资源初始化不彻底从⽽出现⼤量请求超时、阻塞、报错甚⾄导致刚发布应⽤宕机等线上发布事故出现。为了避免该类问题业界针对不同框架类型以及应⽤⾃身特点设计了不同的应对举措,⽐如针对类加载慢问题有编写脚本促使JVM进⾏预热、阿⾥巴巴集团内部HSF(High Speed Framework)使⽤的对接⼝分批发布、延迟注册、通过mock脚本对应⽤进⾏模拟请求预热以及⼩流量预热等。本节将对其中适⽤范围最⼴的⼩流量预热⽅法进⾏介绍。

相⽐于⼀般场景下,刚发布微服务应⽤实例跟其他正常实例⼀样⼀起平摊线上总QPS。⼩流量预热⽅法通过在服务消费端根据各个服务提供者实例的启动时间计算权重,结合负载均衡算法控制刚启动应⽤流量随启动时间逐渐递增到正常⽔平的这样⼀个过程帮助刚启动运⾏进⾏预热,详细QPS随时间变化曲线如图6所示:

image.png

图6 应⽤⼩流量预热过程QPS曲线

开源Dubbo所实现的⼩流量服务预热过程原理如下图7所示:

image.png

图7 应⽤⼩流量预热过程原理图

服务提供端在向注册中⼼注册服务的过程中,将⾃身的预热时⻓ WarmupTime、服务启动时间StartTime 通过元数据的形式注册到注册中⼼中,服务消费端在注册中⼼订阅相关服务实例列表,调⽤过程中根据 WarmupTime、StartTime 计算个实例所分批的调⽤权重。刚启动StartTime 距离调⽤时刻差值较⼩的实例权重下,从⽽实现对刚启动应⽤分配更少流量实现对其进⾏⼩流量预热。

开源Dubbo所实现的⼩流量服务预热模型计算如下公式所示:

image.png

模型中应用QPS对应的 f(x) 随调用时刻 x 线性变化,x表示调用时刻的时间,startTime是应用开始时间,warmupTime是用户配置的应用预热时长,k是常数,一般表示各实例的默认权重。

image.png

图8 应⽤⼩流量预热权重计算

通过⼩流量预热⽅法,可以有效解决,⾼并发⼤流量下,资源初始化慢所导致的⼤量请求响应 慢、请求阻塞,资源耗尽导致的刚启动应⽤宕机事故。

3 微服务就绪检查

在介绍微服务就绪检查之间,先简单介绍⼀下相关的Kubernetes探针技术作为技术背景,以便更好的理解后⽂内容:

Kubernetes探针技术

在云原⽣领域,Kubernetes为了确保应⽤ Pod 在对外提供服务之前应⽤已经完全启动就绪或者应⽤Pod⻓时间运⾏期间出现意外后能及时恢复,提供了探针技术来动态检测应⽤的运⾏情况,为保证应⽤的⽆损上线和⻓时间健康运⾏提供了保障。

存活探针

Kubernetes 中提供的存活探测器来探测什么时候进⾏容器重启。例如,存活探测器可以捕捉到死锁(应⽤程序在运⾏,但是⽆法继续执⾏后⾯的步骤)。在这样的情况下重启容器有助于让应⽤程序在有问题的情况下更可⽤。

就绪探针

Kubernetes 中提供的就绪探测器可以知道容器什么时候准备好了并可以开始接受请求流量,当⼀个 Pod 内的所有容器都准备好了,才能把这个 Pod 看作就绪了。这种信号的⼀个⽤途就是控制哪个 Pod 作为 Service 的后端。在Pod 还没有准备好的时候,会从 Service 的负载均衡器中被剔除的。

启动探针

Kubernetes 中提供的启动探测器可以知道应⽤程序容器什么时候启动了。如果配置了这类探测器,就可以控制容器在启动成功后再进⾏存活性和就绪检查,确保这些存活、就绪探测器不会影响应⽤程序的启动。这可以⽤于对慢启动容器进⾏存活性检测,避免它们在启动运⾏之前就被杀掉。

探针使用小结

1.当需要在容器已经启动后再执⾏存活探针或者就绪探针检查,则可通过设定启动探针实现。

2.当容器应⽤在遇到异常或不健康的情况下会⾃⾏崩溃,则不⼀定需要存活探针,Kubernetes 能根据 Pod 的 restartPolicy 策略⾃动执⾏预设的操作。

3.当容器在探测失败时被Kill并重新启动,则可通过指定⼀个存活探针,并指定restartPolicy 为Always 或 OnFailure。

4.当希望容器仅在探测成功时 Pod 才开始接收外部请求流量,则可使⽤就绪探针。

更多Kubernetes探针技术使用示例参考[2]。

当前容器+Kubernetes的应⽤运维部署⽅式已经成为了业界的事实标准,相关技术为微服务应⽤运维部署带来巨⼤便利的同时,在某些特殊的应⽤部署场景中也有⼀些问题需要解决。⽐如,使⽤Kubernetes的滚动发布功能进⾏应⽤发布,由于Kubernetes的滚动发布⼀般关联的就绪检查机制,是通过检查应⽤特定端⼝是否启动作为应⽤就绪的标志来触发下⼀批次的实例发布,但在微服务应⽤中只有当应⽤完成了服务注册才可对外提供服务调⽤。因此某些情况下会出现新应⽤还未注册到注册中⼼,⽼应⽤实例就被设置下线,导致⽆服务可⽤。

针对这样⼀类微服务应⽤的发布态与应⽤运⾏态⽆法对⻬的问题导致的应⽤上线事故,当前业界也已经有相关解决⽅案进⾏应对。⽐如可以通过就绪检查关联服务注册的⽅法,通过字节码技术植⼊应⽤服务注册逻辑前后,然后在应⽤中开启⼀个探测应⽤服务是否完成注册的端⼝供Kubernetes的就绪探针进⾏应⽤就绪态探测进⽽绑定⽤户的发布态与运⾏态实现微服务的就绪检查,避免出现相关状态不⼀致导致的应⽤发布上线流量有损问题。

参考资料

[1] Dubbo延迟注册:https://dubbo.apache.org/zh/docs/advanced/delay-publish/

[2]Kubernetes探针技术使⽤实例:
https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

本文摘选自《微服务治理技术白皮书》,白皮书免费下载地址:https://developer.aliyun.com/ebook/7565

image.png


云数据库RDS MySQL从入门到高阶训练营开始免费报名啦!

大咖带你学习云数据库RDS MySQL,从入门基础架构和性能调优,到高阶MGR和云原生serverless。

本次是阿里云联合中国MySQL用户组,为大家重点介绍MySQL数据库基础的架构、SQL性能调优等内容,以及高阶的MySQL MGR等特性,让您对MySQL数据库在短时间内有一定的了解。同时,您还将有机会在实验环境中实操体验SQL诊断与调优,以及申请体验最新的Serverless能力,七天时间轻松入门 RDS MySQL数据库,完成技术成长与职业突破!

点击这里,查看详情!

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
2天前
|
监控 持续交付 开发者
构建高效微服务架构:从理论到实践
【2月更文挑战第25天】本文旨在深入剖析微服务架构的核心概念、设计原则以及实践中的关键技术挑战。通过探讨微服务的独立性、分布式特性和弹性机制,文章为读者提供了一套系统化的方法论,以指导如何构建和维护一个高效、可扩展且容错性强的微服务系统。文中将结合案例分析,展示微服务架构在真实业务场景中的应用,并提供性能优化和故障恢复的策略建议。
27 3
|
22小时前
|
安全 数据管理 API
构建高效微服务架构:从理论到实践
【2月更文挑战第27天】 在数字化转型的浪潮中,微服务架构已成为企业追求敏捷、灵活与可扩展性的关键解决方案。本文将深入探讨微服务的设计原则、开发流程以及如何在实际项目中实现一个高性能的微服务系统。我们将通过分析微服务的核心优势,揭示其背后的技术挑战,并提供一系列切实可行的策略来优化微服务的性能和稳定性。文中不仅包含了丰富的理论依据,还结合了实际案例分析,为开发者和企业决策者提供了一套全面的微服务实施指南。
|
1天前
|
消息中间件 敏捷开发 运维
构建高性能微服务架构:策略与实践
【2月更文挑战第27天】 在当今快速迭代和持续部署的软件发展背景下,微服务架构因其灵活性、可扩展性和技术异构性的优势而成为众多企业的首选架构模式。然而,随之而来的复杂性管理和性能优化问题也不容忽视。本文深入探讨了构建高性能微服务架构的策略与实践,包括服务拆分原则、通信机制、数据一致性保障以及监控和故障处理等方面。通过分析具体案例和最佳实践,旨在为开发者提供一个清晰、高效的微服务性能优化路径。
|
1天前
|
监控 Kubernetes Docker
构建高效可扩展的微服务架构
本文将详细介绍如何构建高效可扩展的微服务架构,包括设计原则、技术选型和实施步骤。通过采用微服务架构,企业可以实现系统的解耦、灵活性和可伸缩性,提升开发效率和系统性能。
|
1天前
|
存储 Java 持续交付
构建高效微服务架构:从理论到实践
【2月更文挑战第26天】在现代软件开发的浪潮中,微服务架构已成为企业追求敏捷、可扩展和易于维护系统的重要解决方案。本文将深入探讨微服务的核心概念、设计原则以及如何在实际项目中实施微服务架构。我们将通过一个示例来揭示拆分传统单体应用的步骤,并讨论微服务架构在提高开发效率、支持快速迭代和优化资源使用方面的优势。同时,我们也将指出微服务实施过程中可能遇到的挑战,如服务发现、配置管理和分布式事务处理,并提出相应的解决策略。
|
2天前
|
监控 负载均衡 API
深入理解微服务架构下的API网关
【2月更文挑战第26天】在现代后端开发中,微服务架构已经成为一种主流的系统设计方式。本文将重点探讨微服务架构中的关键组件——API网关。我们将分析API网关的核心功能,包括请求路由、负载均衡、认证授权、监控和日志记录等。此外,文章还将讨论如何在实际项目中设计和实现一个高效、可扩展的API网关,以及它对微服务治理的重要性。通过本文,读者将获得对API网关在微服务架构中的重要作用和应用策略的深刻理解。
|
2天前
|
负载均衡 算法 微服务
常见的微服务流量治理策略
常见的微服务流量治理策略
15 3
|
2天前
|
消息中间件 负载均衡 API
构建高效微服务架构:策略与实践
【2月更文挑战第25天】在数字化转型的浪潮中,微服务架构以其灵活性、可扩展性成为企业技术升级的关键选择。本文深入探讨了构建高效微服务架构的策略和实践方法,旨在为开发者提供一套系统的设计与实施指南。文中不仅阐述了微服务的核心概念和优势,还详细分析了在设计、部署和维护微服务过程中可能遇到的挑战及解决方案,同时结合案例分析,展示了如何在实际项目中落实这些策略。
|
4天前
|
消息中间件 Kubernetes Java
构建高性能微服务架构:从理论到实践
【2月更文挑战第24天】 在当今快速发展的数字化时代,微服务架构已成为软件开发领域的关键趋势。本文将深入探讨如何构建一个高性能的微服务系统,包括关键的设计原则、技术选型和性能优化策略。我们将通过实际案例分析,揭示微服务架构在提高可伸缩性、容错性和维护性方面的优势,并讨论在实施过程中可能遇到的挑战及其解决方案。
|
5天前
|
Kubernetes 开发者 Docker
基于容器技术的微服务架构
基于容器技术的微服务架构
10 0

相关产品

  • 微服务引擎
  • 服务网格