淘宝应用柔性架构的探索

Reactive 全异步化

当前我们的微服务主要是基于同步的调用模型,带来了如下挑战:

  • 同步等待造成应用资源利用率很难进一步提升
  • 并发度有限,技术实现无法做到业务理想程度的并发,导致 RT 增加
  • 下游出现问题会导致应用本身出现问题(如应用等待下游响应的线程会被长时间阻塞)

为此,我们引入了基于 Reactive 编程模型,以全异步、可编排的能力,来应对上述挑战:

  • 通过全异步化使得资源利用率 / 性能进一步提升
  • 通过全异步化,编排能力,使对外调用的请求并发能够突破原有并发线程的限制,做到极致并发
  • 通过全异步化能力,使得应用在等待依赖响应的耦合资源从线程变成了回调对象,让下游出问题时对应用自身的影响变得十分有限,从而提升了应用本身的稳定性。

基于 Reactive 全异步的解决方案打通了全栈,使得应用能够进行全异步化升级。淘宝的一核心推荐应用,在上线后 QPS 上涨了 90%+,另一核心应用,上线后 RT 也下降了 40%。

关注稳定性

在全异步化解决方案落地的同时,我们也在持续关注着稳定性。业务规模不断的增加,对稳定性的挑战也在变得越来越大。尽管我们对稳定性非常重视,但有时还是难免因一些错误的判断而导致了稳定性问题。

比如,在某次大型活动中,我们的收获地址出现了一些短暂不可用问题;又比如,在另一次大型联欢活动中,我们的登录系统也出现了短暂的不可用问题。这两个经典的案例,都是在我们对应用的容量、活动的流量预估上出现了失误而导致的问题。

虽然通过限流,我们可以大幅度提升应用在流量方面的稳定性,但通过上述两个案例,以及业务的不断实践,我们认为,只使用静态限流,系统还是会因为一些不确定性因素而带来稳定性上的隐患和风险。

由不确定性而引发的问题

限流是保护应用稳定性的有力武器,应用在正确预估自身容量和外部流量的情况下,借助限流可以保护应用自身不被流量打垮,从而提高自身的稳定性,淘宝这么多年的活动,限流都起到了功不可没的稳定性作用。

随着微服务数量的增长,我们发现应用在使用静态限流时,也带来了一些稳定性的隐患 —— 静态限流 与 不断演进的应用之间存在着时间上的不匹配。换句话说,应用一旦设置了限流,只要应用不断的发展,静态限流就有可能面临着过时的风险。造成过时隐患和风险的因素主要包括:

1、业务演进 / 依赖变化引起的不确定性

  • 业务一直在发展,我们的应用代码也一直在变化,很有可能昨天刚刚设置过的限流 QPS,在今天应用一发布,就已经不适用了。就算应用本身不发布,应用自身依赖的后端服务的拓扑不停的变化,也会引发应用能够承受的 QPS 发生变化,带来不确定性

2、流量模型发生变化引起的不确定性

  • 应用和服务通常包含多种方法调用,每种方法调用消耗的系统资源都不同,这要求在对应用压测时的流量模型要足够的合理准确,才能找到有效的限流值,然而业务的流量模型往往也是在不断的变化,这也会为应用的 QPS 评估带来不确定性。

3、不同容器实例容量引起的不确定性

  • 随着运维环境和方法越来越复杂,交付给业务的容器,也变得不确定,如我们的混部、CPU Sharing 。同时,同一应用的不同容器,很可能会有不同的容量,如同一个应用的不同容器,压出来的基线 QPS 都很可能有很大的差异。底层机器资源的不确定性,也为应用限流 QPS 评估带来了不确定性

因此,针对应用的限流阈值设置,应用开发就会很纠结:

  • 如果设置的限流阈值偏保守(偏低),那么:有的机器资源使用率上不去,浪费机器,造成成本升高问题。
  • 如果设置的限流阈值偏乐观(偏高),那么:有的机器还没有达到限流阈值,就会被压垮,造成稳定性问题。

上述的不确定性,也是我们在大型活动前,进行封网的原因之一。

应用柔性架构升级

面对着如此多的不确定性,我们希望我们的应用本身能够具有一些『柔性』的特征,使得在面对不确定的场景突然出现时,应用仍能够承受这些变化,就像太极一样,能够做到以柔克刚。我们认为,应用架构要做到柔性,至少需要有以下特征(针对应用柔性架构的特征,我们也在持续的探索中):

1、故障容忍

  • 如使用隔离进行解决。阿里的异地多活单元方案,可以隔离地区出现的问题;微服务化提升了研发效率,同时也隔离了其他独立链路出现的问题;而我们提出的全异步化解决方案,也增加了上游对下游出问题时的隔离作用。

2、过载保护

  • 如使用自适应负载调节进行解决。来应对由于流量容量预估不准而带来的稳定性问题。

为解决上述提到的不确定性带来的应用过载隐患问题,我们引入了自适应负载调节来升级应用的过载保护能力,解决应用过载的稳定性隐患。

自适应负载调节

通过自适应负载调节来应对上述不确定性,使得应用能够就地实时的评估自身负载,让接受的 QPS 与处理能力同步,防止限流评估出错而导致的稳定性问题和资源利用率问题;同时,在应用接收到超高压时,单机压垮的 QPS 可提到更高。从而能够应对更高的突发流量,加固应用自身的稳定性。

整个方案的主要由两部分构成:

1、与应用整合的负反馈组件

  • 在应用的入口设置一个负反馈组件,根据应用自身的负载情况,对进入的请求进行针对性的拦截
  • 为了适用更多业务,此组件还支持服务权重,优先拒绝权重低的服务,使得在过载时,资源能够尽量往权重高的服务倾斜。

2、组件本身的快速迭代机制

  • 为了让方案本身能够在不同的场景下有效,我们从很多不同的维度展开,组合成多个场景,再通过自动化的场景压测,来快速进行算法在不同场景下的效果评估和改进,从而提升整个方案的迭代演进速度。

最终,整个方案沉淀了自适应负载调节的自动迭代平台,迭代出基于 CPU 的自动控制算法。

上线案例

淘宝某核心业务的应用,在一次大型活动压测中的效果得到验证:在某个机房的机器数比预期少 22.2% 的情况下,抗住了 130% 的压测流量。按照以往双十一的压测经验,在少这么多机器的情况下,这个机房的应用扛不住如此大的流量。

另一核心应用,由于担心不确定性原因,静态限流值设置的偏保守,在接入自适应负载调节后,限流值可以进一步提升,使得服务的有效 QPS 提升了 23s0%,同时应用的压垮 QPS 提升了 3 倍,在压测大流量过后,秒级恢复,迅速提供正常服务(原需 6 分钟 + )。

应用柔性架构升级 - 后续展望

为了让应用更具高可用,我们从故障的角度,围绕着从故障发生前的预防能力,到故障诱因发生中的防御能力,再到故障发生时的恢复能力,来打造应用的高可用能力,进行应用的柔性架构升级。

同时,针对自适应负载调节,目前的策略为就地拒绝,提高了稳定性,但仍有稳定性风险,后续我们需更进一步丰富策略,如结合集团的中间件产品,进行快速扩容 / 缩容操作;应用向上游反馈压力,使得压力从上游杜绝(分布式回压)等。同时,为了在应用的依赖出现问题时,仍能够有柔性能力,我们也会针对同步模型的应用,引入自适应的隔离 / 熔断能力,使得应用下游出现问题时,不会影响到应用本身。

应用高可用关注的是应用自身,除了应用高可用,我们也在积极推进淘系业务整体的高可用能力,比如在站点出现问题时,我们如何做到以最快的速度切换流量,恢复业务,最终提升整个淘系的高可用。更多关于应用高可用、淘系业务高可用的理解和落地,我们在持续地探索。

本文转载自公众号淘宝技术(ID:AlibabaMTT)。

原文链接:

https://mp.weixin.qq.com/s/uW8gNGCI-oj4NitU9dHZjQ

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章