开发者社区 > 博文 > 【稳定性】浅谈618大促稳定性之容量设计
分享
  • 打开微信扫码分享

  • 点击前往QQ分享

  • 点击前往微博分享

  • 点击复制链接

【稳定性】浅谈618大促稳定性之容量设计

  • fe****
  • 2024-06-15
  • IP归属:北京
  • 100浏览

    背景

    每年618大促,相信大家对于大促稳定性保障这个词都不陌生。在大促活动期间,如何确保系统的稳定性和容量设计,是每个电商平台都需要面临的重要问题。回归问题本质,系统在大促的稳定性和日常稳定性的区别在哪呢?个人理解核心是两点:

    1、【技术】高并发流量:大促流量峰值是日常的N倍(几十、几百倍),需要具备更高的并发流量处理能力,以保证系统的稳定性。

    2、【业务】业务场景多样化:大促会增加很多日常用不到的场景,很明显的比如预售场景等。

    本文将探讨大促稳定性容量设计的关键策略,由于能力有限,仅供大家参考,如里面信息不对请指正,如有更好方法麻烦帮忙补充。谢谢!

    容量规划

    容量规划的本质是追求计算风险最小化和计算成本最小化之间的平衡,只追求任意其一都不是合理的。为了达到这两者的最佳平衡点,需尽量精准计算系统峰值负载流量,再将流量根据单点资源负载上限换算成相应容量,得到最终容量规划模型。

    运用各种方法和工具来保障软件系统的容量可以承载并处理各种业务,并且本身还要具备一定的弹性能力。这里的弹性能力是说系统本身要有比较灵活的扩缩容功能,当遇到突发的场景或者故障时,需要具备弹性的自愈能力。

    容量规划设计的挑战

    1)容量的不确定性。由于电商的业务场景是非常复杂的,尤其在大促期间,存在各种突发流量场景。

    2)容量评估的复杂性。本身容量治理是非常复杂的工程,系统架构复杂,对庞大的软件系统做容量评估并非易事。

    3)容量测试的精准性。容量评估后,我们需要通过各种手段,比如军演全链路压测、故障演练来测定和验证,之后才能进行后续的容量规划治理。

    4)容量规划治理的复杂性。在进行容量规划的过程中,得先解决很多其他问题,比如环境的问题,环境不一样,所需的资源配置不一样,测试的业务场景和实际生产场景之间可能会存在一定差异;而且业务是不断迭代的,线上系统在不断地发版,代码逻辑可能一直在变,所以容量规划本身是一个持续性的技术动作

    一、流量模型评估

    单量趋势

    根据日常及历史大促数据,预测今年大促单量的趋势图。但业务单量只能间接呈现系统压力同比趋势,而作为研发从技术视角出发,应该关注各自应用接口调用量峰值的增幅、出现的时间点及持续时长,我们要根据相应接口的同环比峰值,日常的调用量增幅,调用渠道,技术改动影响并结合业务行为策略来做出更专业的评估。

    1)入口流量

    对于一次大促,系统峰值入口流量一般由常规业务流量与非常规增量(比如业务运营策略变化&容灾策略带来的流量模型配比变化)叠加拟合而成。

    常规业务流量一般有两类计算方式:

    1.1、历史流量算法(常规):

    该类算法假设当年大促增幅完全符合历史流量模型,根据当前&历年日常流量,计算整体业务体量同比增量模型;然后根据历年大促-日常对比,计算预估流量环比增量模型;最后二者拟合得到最终评估数据。由于计算时无需依赖任何业务信息输入,该类算法可用于保障工作初期业务尚未给出业务总量评估时使用,得到初估业务流量。案例如下:

    • 原则:备战系数每个业务根据自身历史数据情况来评估和预备机器资源
    • 预估口径:比如往年大促峰值的1.3倍
    • 各机房承载流量分布:不同机房流量不同

    1.2、业务量-流量转化算法

    该类算法一般以业务预估总量为输入,根据历史大促&日常业务量-流量转化模型,换算得到对应子域业务体量评估。该种方式强依赖业务总量预估,可在保障工作中后期使用,在初估业务流量基础上纳入业务评估因素考虑。


    案例:云仓时效流量转化预估算法
    背景:由于今年新增加了云仓某种类型不同时效,时效主要是给零售侧商详页返回时效、结算页展示日历,下单后时效控制及全程跟踪信息

    流量转化算法依赖的维度:QPS= STORE(仓库数量占比) & SKU(仓库对应SKU数量级)& 日常云仓时效流量占比(云仓时效流量/时效总流量) & 热SKU(是否存在热点的SKU(比如 苹果,茅台等热门,秒杀的SKU))

    1、结合上面的历史流量算法,可预测今年618时效流量总值
    2、根据云仓独立时效的占比,比如配置了时效的仓库是N,其中云仓是M。算出来 云仓独立时效配置 占比 M/N=xx%。但是商详结算流量峰值是根据SKU来的,所以广统计仓库占比这个维度是没有用的
    4、统计 云仓的SKU数量 和 自营仓SKU 数量 ,是不是一个数量级上,如果是则可参考仓库,如果不是需做对应的处理。
    5、结合日常 云仓独立时效流量峰值,跟全部仓时效流量峰值,比对,看看日常占比是多少
    6、另外需重点考虑:云仓是否存在热点的SKU(比如 苹果,茅台等热门,秒杀的SKU),因为这样的1个SKU的流量峰值可等于N万个SKU

    1.3、非常规增量流量预估算法

    一般指业务营销策略变更或系统应急预案执行后流量模型变化造成的增量流量。

    案例1:上游本来调用A接口1次,由于业务策略变更,上游同一个场景会调用N次(N=2),则618大促流量峰值预估值=常规流量预估的往年大促峰值流量 * N倍
    案例2:比如去年618峰值是1万/秒,最近半年业务运营发展快,日常峰值已经达到了1.5W/S,这时候肯定不能按去年618大促峰值来预估,而是根据去年618日常 和今年大促/日常  同环比比较,并且结合业务大促运营策略 综合评估


    考虑到成本最小化,应急预案等非常规增量计算时一般无需与常规业务流量一起,一般会将非常规策略发生概率作为权重。

    2)节点流量

    节点流量由入口流量根据流量分支模型,按比例转化而来。分支流量模型以系统链路为计算基础,遵循以下原则:

    • 同一入口,不同链路占比流量独立计算。
    案例:比如下单后大件流量=下单后流量 * 大件链路占比
    • 业务降级
    案例:比如A业务去年降级了,今年不降级,那需要考虑今年的流量,根据去年日常,今年日常变红趋势,上游沟通等综合预估
    • 针对同一链路上同一节点,若存在多次调用,需计算按倍数同比放大(比如DB\Redis等)。
    案例:批量List接口调用,则DB流量=List.size()
    • DB写流量重点关注,可能出现热点造成DB HANG死。

    根据上面的流量模型评估对应API流量,结合链路分析,系统一般是有网络设备、WEB服务器、数据库、缓存、消息队列等组成的复制集群,在分布式系统中,任何节点出现瓶颈,都有可能导致雪崩效应,最后整个集群垮掉。所以,要规划整个平台的容量,就必须计算出每一个节点的容量,找出任何可能出现的瓶颈所在。

    二、数据增长预测

    1、数据库访问量:计算服务实现中对每一个数据库的访问量,可以表达为每秒/分事务数(TPS/TPM)或每秒/分查询数(QPS/QPM),确保对数据库的访问量在数据库可承受范围内。

    2、数据库数据增长量:计算数据的增长量,增长量可以表达为每日、每小时增加的记录条数、增加的数量存储量。确保数据增长量在数据库与存储可承受范围内。

    3、数据库性能:在大促活动期间,数据库的读写压力会显著增加。因此,优化数据库性能是提高系统稳定性的关键(比如数据库连接池、索引优化,读写分离,分库分表等)

    4、数据库连接池:在给定的服务访问量下,针对数据源连接数(MAX/MIN)配置预估与设计,合理连接数的粗略估算方法可以通过事务并发数与事务长度来进行。如事务并发数是100TPS,事务长度是500ms,则MAX连接数至少要大于50(100TPS*0.5s)。但合理的连接数最好通过性能压测获得,或者根据处理模式与访问量相似的系统的生产数据推测。设置最大连接还必须同时评估对数据库总连接数的影响以及与对JVM内存的影响。在无可参照系统的情况下,最稳妥的方式是通过压力测试来验证。同时,严格设定连接池的BLOCK_TIMEOUT值,确保系统在故障时期的容量和性能。若服务瞬时并发量大,建议考虑数据库连接池和预编译SQL语句预热设计,规避应用发布或重启后的瞬间流量冲击。

    5、缓存预热:使用缓存可以有效减轻数据库的压力,提高系统性能。在大促活动期间,可以适当增加缓存容量,将热点数据和频繁访问的数据存储在缓存中。同时要设置合适的缓存过期策略,以保证数据的实时性和准确性。

    6、其他数据服务访问量与数据增长量:除数据库之外的其他数据服务访问(如缓存、搜索等),可参考数据库访问量与数据增长量的评估方式进行评估,确保数据服务的访问量与数据增长量在可承受范围内。

    三、Redis峰值QPS流量(其他数据中间件可参考)

    需要考虑:不同应用、不同分组下的机器个数、应用的API个数,每个API流量,API里方法Redis次数,最终定位Redis流量

    影响流量公式:QPS= C(在线客户端连接数量) & A(每个应用的API)& J(API访问Redis次数,比如1个API内部访问10次Redis和1个API访问1次Redis)

    备注:因为Redis的写都是访问m实例,故这只讨论Redis缓存的读操作

    下面详细讲解下每个影响因子:

    1、C(在线客户端连接数量)

    通过Redis客户端列表》每个config对应的在线客户端数量,核心需要关注后面配置读组实例S及读策略

    表面看起来在线客户端数量差不多,但这只是表示jdos机器个数

    2、 A(每个应用的API)

    需要评估对应机器上的应用对应API个数,比如A应用只有1个接口,但B应用有10个接口。这些接口的峰值时间可能不一样,需要参考大促峰值期间比如20点或者0点对应 各接口流量峰值

    3、J(API访问Redis次数)

    比如1个API内部访问10次Redis和1个API访问1次Redis是不一样的。尤其是一些批量接口更加如此。

    结合上面的综合评估,最终去调整Redis主从上的config对应的S实例流量均衡。

    附:当然上面评估算法是理论并且耗时耗力,如果接口参与过大促并且无改造,可根据往年618前和现在日常数据为基础,根据常规历史流量算法预估。

    四、MQ消息量

    计算服务处理消息量与消息体大小,确保不超过消息中心(或消息队列)的承载能力。若承载能力无法支持,则考虑对消息中心进行扩容支持。如果涉及到跨IDC消息投递,需要进行跨机房消息性能和容量的评估,原则上非必要不建议跨机房消息投递。

    针对消费JMQ场景要验证什么:
    JMQ2不开并行:JMQ服务端出队能力 = 分片数量*队列数*批量大小*(1000/tpAvg)* 0.9
    JMQ2开并行:    JMQ服务端出队能力 = 分片数量*队列数*并行窗口大小*(1000/tpAvg)* 0.9
    JMQ2分片数 * JMQ2的队列数 = JMQ4的分区数
    影响消费速度的三个因素:onMessage方法性能平均值(tpAvg)、客户端线程数、服务端队列数
    常见问题:
    a.出队能力不足,客户端消费能力不足,导致积压(置备相应的出队能力和客户端消费能力)
    b.平时入队量与出队量都小,平时消费无问题。 一旦入队量激增,出队量跟着激增时,消费逻辑中依赖的接口、数据库、中间件受压性能变差甚至不可用。(置备相应的消费能力或限制消费速度)
    MQ压测验证点:需要压到或憋到与以往大促相同的入队量级*备战系数
    不允许积压:出队能力>入队能力,目标使变量tpAvg是稳定的,执行最大出队能力时消费逻辑中依赖的接口、数据库、中间件稳定承压。   。
    允许一定积压: 出队能力<入队能力,目标使变量tpAvg是稳定的,执行最大出队能力时消费逻辑中依赖的接口、数据库、中间件稳定承压。

    总结:估算好入队、置备好出队,tpAvg稳定 <----压或憋验证

    五、内部资源使用

    线程池配置:在给定的服务访问量下,确定每一个线程池的配置的合理性。线程池过小,将无法足够的并发能力来支撑所需要的服务访问量,线程池过大,则可能超过一个JVM可以支持的线程总数,且对性能可能产生负面影响。建议使用有界线程池,避免造成线程数量不可控。建议通过压测对线程池配置进行调优,在满足并发要求下,采用最小的线程池配置。

    网络连接池配置:在给定的服务访问量下,需要确定每一个网络连接池配置的合理性。网络连接池过小,将无法提供足够的并发能力来支撑所需要的服务访问量,连接池过大,则对网络设备与目标服务器产生过大的压力,且对性能可能产生负面影响。建议通过压测对网络连接池配置进行调优,在满足并发要求下,采用最小的网络连接池配置。

    JVM配置:评估JVM内存配置、GC算法与参数配置是否合理。通常情况下,JVM配置可以根据线上参考系统(应用的架构、典型处理模式、访问量与访问模式等)进行配置。但如果应用有特殊需求(比如开设了大的内存缓存、队列,或者对响应时间与吞吐量有特殊要求等),需要进行专门调优,并对调优结果进行性能与稳定性测试。需要注意的是,所有的内存缓存、队列以及内部其它数据结构查询等都必须设置大小上限,并计算或测试当上限达到时不会出现堆内存溢出的情况。一个容易出现的问题是使用内存数据结构作为批量查询或文件处理的缓冲区,当输入数据量过大或者并发度太高时,堆内存就耗尽了。

    六、伸缩性

    1、复制性伸缩:应用复制型伸缩是所有应用都必须具备的能力,因为应用必须是无状态的,可以通过在集群中添加应用服务器实例,可以接近线性地扩展集群容量。对访问量大、读写比高、数据一致性要求低的场景,可考虑缓存与读写分离策略,实现数据复制。应用必须具备容忍一定的数据复制延时造成的数据不一致的能力。

    2、垂直性伸缩:应用垂直型伸缩是指按照功能将应用拆分。需要评估应用拆分与业务架构、应用架构、非功能性需求的匹配度以及粒度是否合理。数据的垂直型伸缩也是指按照功能对数据拆分,同样需要评估数据拆分与业务架构、应用架构、非功能性需求以及运维成本的合理性,取得各方面综合最优的方案。

    3、水平性伸缩:水平型拆分主要针对数据,是指按照用户或请求的维度对数据进行水平拆分。若预判未来业务量增长必须通过数据水平拆分才能支撑,需要在早期实现中就实现数据水平拆分,避免未来重构的成本与风险,行业内水平拆分的技术可以参考TDDL等技术。

    七:链路分析

    1、同步调用链分析:过长的同步调用链对性能、容量、可靠性都是极大的风险,整个处理的响应时间是链条中每一环的处理时间之和,链条中的任意一环出现故障或缓慢,都会造成整个处理缓慢或失败,所有的服务访问量会压到同步处理链条中的每一环,且每一环存在大量的线程等待(阻塞线程资源甚至更昂贵的数据库连接资源)。

    降低同步处理链路长度的通常做法有:控制系统的拆分粒度,优化系统的职责;对于大访问量的处理(每日千万级或以上),可考虑将远程调用固化成本地处理,牺牲一些灵活性换取稳定性与性能;异步化。

    2、响应时间分析:需要对所有服务的响应时间进行分析。服务处理的响应时间取决于它所直接依赖的内、外部业务或系统服务的处理响应时间,它自身的处理时间、以及请求排队等待的时间。对响应时间的评估不是一个绝对值,而应该是一个响应时间区间。需要找到瓶颈点进行分析与优化,确保响应时间区间满足客户端的需要。

    八、吞吐量提升

    在实践中,由于资源的有限和调配存在延迟,通过提升系统性能不仅在资源上能降低成本,在稳定性上也有着积极意义,可以降低用户体验延迟,减少机器高负载时不稳定的概率。

    基础设施优化:依赖数据库、中间件等通过优化配置、技术创新等针对性能进行优化,例如gc调优、慢sql治理等。

    业务流程优化:降低调用次数、多次网络调用优化批量调用、非核心逻辑异步处理、根据负载自动化削峰填谷设计等。

    九、容量应急预案

    根据容量评估、军演全链路压测、性能压测的结果,最终修正对应流量峰值,然后设定限流、服务降级等系统保护措施,来预防当实际流量超过系统所能承受的最大流量时系统无法提供服务。


    由于容量规划这个知识点挑战性很大,本文也是结合日常实践经验,浅谈部分知识点,供大家参考,如里面信息不对请指正,如有更好的方法麻烦帮忙补充。谢谢!

    参考:

    信通院稳定性建设

    https://my.oschina.net/5129714/blog/7119017

    https://developer.aliyun.com/article/782540

    https://xie.infoq.cn/article/036019d2cf2c49f168e0120ef