本文分享自华为云社区《逻辑多租场景下,故障爆炸半径的控制实践》,作者:王福强 陈子栋。
背景
某系统是一款华为自研的工具平台,可部署在公有云上,面向全球多项目、多客户提供服务。为了满足数据安全合规要求,并尽可能降低用户使用成本以及提升运维效率,整体上采用了混合多租的设计方案,逻辑层通过ID识别不同租户实现请求分流,各租户的开发者可在租户内开发独立的APP,例如web或终端页面、数据模型、服务、接口等。
在日常运行过程中,由于多租户共享同一个平台资源,而各租户APP性能千差万别,单租户过载、应用死循环等导致的平台级故障时有发生,而这些不确定性应用场景却承载在相对确定的底层计算资源和平台服务之上,给系统整体稳定性带来了严峻挑战。
(备注:本文中的故障特指逻辑多租场景下,单个租户自开发的APP异常引发的平台故障,不包括平台软件bug导致的故障。)
多租架构形态介绍
该系统采用混合多租架构,针对公共服务(如登录鉴权等)采取共享模式,全部用户同享同一集群;针对业务逻辑处理单元,按照租户的等级与规模分别按需配置资源独享(物理多租)或共享(逻辑多租)。
物理多租:服务集群为单租户独享,部署在独立的云服务资源上,租户间故障充分隔离。
逻辑多租:共享服务集群可以处理多个租户的请求,当性能不足时可以通过在堆栈内增加实例来提高性能,多个实例对外提供负荷分担的能力。
如下图所示,租户A和租户B配置为逻辑多租,租户C配置为物理多租。
系统多租架构示意
故障爆炸半径过大的典型问题分析
对于逻辑多租来说,租户间有一定的资源隔离能力,但仍会发生资源抢占的问题,比如故障爆炸半径过大的典型问题,在逻辑多租的架构下,资源无法做到完全隔离,而且由于租户内部开发的APP质量参差不齐,比如存在慢SQL、慢服务,或JS代码死循环、APP内部服务间循环调用等问题,当这些问题导致某个租户的APP服务请求异常时,如果不加以控制,爆炸半径可能会由单个功能故障逐步扩大整个租户故障,甚至整个平台故障。典型故障场景如下:
1.单个JS占用过多CPU和内存,导致整个JVM宕机,影响到整个服务集群。
单JS占用过多CPU和内存
2.服务循环调用或调用链过深,单次请求占用系统过多资源,导致其他服务无可用资源,请求失败。
服务循环调用或调用链过深
3.单个租户请求占用系统过多连接池/线程池,导致其它租户无可用资源,请求失败。
单个租服务器托管网户请求占用系统过多连接池/线程池
从上述故障场景可以发现,平台上各租户的APP运行逻辑存在很大的不确定性,因此很难通过几个单点措施来解决所有问题。所以,针对SaaS逻辑多租场景,就需要提供系统性的高可靠方案,来应对单租户APP异常场景下的爆炸半径扩大的风险。
故障爆炸半径分级控制实践
为应对上面提到的典型故障场景,我们采用了故障分级隔离方案,包括实例内资源限额&限流、APP级资源隔离以及租户级资源隔离,通过事前合理规划隔离资源、事中快速调度隔离资源、事后优化隔离策略,将故障爆炸半径控制到平台级以下。实例内资源限额&限流方案根据历史发生过的故障经验,实例内资源限额与限流可通过3个关键能力+4个控制点来实现:
3个关键能力:包括对单服务内JS对计算资源消耗的控制、单租户请求并发数控服务器托管网制以及租户内单事务执行性能控制。
4个控制点:从资源调用的业务流来看,资源限额与限流的关键控制点有4个,分别为浏览器调用服务端,服务端内JS引擎执行,服务端调用数据库和服务间调用。
基于以上关键控制点,匹配如下关键能力来控制接口请求的流量和资源,最终实现将特定性能过载场景的故障爆炸半径控制在实例内部:
落地实践:
基于产品能力,设计实例内资源限额的上限和下限值。
结合测试环境和现网的运行数据,设置合理的限额值。
对限额与限流结果进行跟踪分析,持续优化限额参数。
APP级资源隔离
单个租户内包含有多个APP,每个APP都有自己独立的页面、服务和模型,但由于所有App共享一套运行引擎,所以我们引入App隔离功能,为不同的App指定不同的运行引擎集群组,从而降低App故障的影响范围。
关键能力:
服务资源基于Group进行分组,服务堆栈在安装部署时指定Group信息。
路由策略由SRE进行管理与下发,最终存储于配置中心供LB与CSE客户端加载。
DMZ-LB负责前端请求路由,根据路由策略,结合各服务location信息,生成具体Nginx配置。
CSE客户端负责后端请求路由,根据路由策略,过滤识别目标服务实例。
落地实践:
基于业务特征合理规划APP隔离资源池,例如将平台APP和定制APP进行隔离,或者将业务A和业务B的APP进行隔离。
对隔离资源池进行性能监控,优化规格参数,确保资源配置合理。
持续识别TOP资源消耗APP,优化资源池数量和APP分布。租户级资源隔离在逻辑多租场景下,不同租户面向不同的企业,各企业对可靠性、性能和变更容忍度均不相同,逻辑多租仅考虑资源复用降低成本,无法彻底保证租户间故障隔离,因此业务还需要支持混合多租能力,将不同租户划入不同的资源组,实现不同租户间的故障隔离。
关键能力:
租户隔离与APP隔离采用同一套能力框架,区别在于APP隔离是将单个租户内的不同APP放到多个平台资源池中,而租户隔离是将不同的租户放到多个平台资源池中。
落地实践:
基于租户差异对资源池进行合理规划和分配,例如高商业价值租户独享,普通租户共享,同时设置观察资源池,用于劣化租户的临时隔离。
对资源池进行性能监控,优化与租户的映射关系,确保资源配置合理。
针对引发资源池性能劣化的租户进行隔离操作,临时分配到观察资源池,完成性能调优后再重新分配资源池。
总结
通过逻辑多租实现资源共享,是一种常见的降低云服务单租成本的有效手段,但是与物理多租相比,也带来爆炸半径不可控的风险。因此需要将单租户资源消耗控制在确定的边界内,以便有效控制故障爆炸半径。本文对多租架构的典型故障场景进行分析,提出应对故障的分级隔离方案,将单租户的运行资源消耗控制在确定的边界内,用确定性的故障隔离机制应对不确定的故障场景,以控制故障爆炸半径,减少平台级故障的发生,在成本与可用性之间实现最优解。
点击关注,第一时间了解华为云新鲜技术~
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
相关推荐: 高效的 Json 解析框架 kotlinx.serialization
一、引出问题 你是否有在使用 Gson 序列化对象时,见到如下异常: Abstract classes can’t be instantiated! Register an InstanceCreator or a TypeAdapter for this t…