ZLJ卖场-全链路压测演进
作者|庄锦弟
原ZLJ卖场的压测流程,是依托于阿里云PTS工具,团队自身缺乏性能测试能力自建,缺少性能分析和数据沉淀,测试场景单一,只有单接口和多接口压测,缺少场景和链路压测,不能相对合理的评估系统性能承载能力,机器扩容只凭借经验进行增加调整,缺乏评估依据。
什么是全链路压测
当接手ZLJ卖场所有业务性能测试后,重新调整性能测试流程和规范,每个项目进行登记,不再是单一接口压测,都需要制定对应的压测场景,后续在双十一、双十二大促的时候,也把全链路压测场景补充进来。在此之前,自已也有了解过一些大厂的全链路压测相关资料,感觉大同小异,差不多都是根据业务特性进行全场的压测,各场景流量大小配置,数据模型,性能分析等等。
业内通用标准:基于实际的生产业务场景、系统环境,模拟海量的用户请求和数据对整个业务链进行压力测试,并持续调优的过程。
要精准衡量业务承载能力,全链路压测就需要做到保持跟生产环境一样:用户规模、业务场景、业务量级和流量来源,目的是让服务系统提前进行峰值承载能力演练,从而达到精准衡量业务实际处理能力的目标,其关键核心:压测环境、测试数据、压测流量(模型)、流量发起、问题定位、分析并调优。
介入全链路压测的时机
在可以预期的一段时间(如双十一、双十二),业务会有较快速的发展,线上机器必须要大幅度扩容
机器扩容以倍数增长,评估机器性能是否翻倍
继续扩容后,服务能力不一定翻倍增长,有可能会受限于其他的依赖关系,如 DB、redis、其他中间件等
ps:业务的不断发展,依赖的模块不断增多,需要找出短板来进行解决
业务线各模块之间交互越来越多
无法单纯以单业务场景的处理能力来评估接口的服务能力
ps:接口的服务能力取决于模块中最低的那个《木桶理论》
对单机压测结果不够准确
性能测试思路
性能模型设计,是什么产品需求,有哪些业务接口,业务量多大,可以参考以往业务数据和压测数据
测试数据及压测脚本的准备,造测试用户,添加为白名单,在压测脚本上添加标签和随机数,作为运营策略过滤条件
确定压测时间段
压测需求对应的关联业务,要把对应技术负责人通知到位,确保压测期间有人支持
压测过程,根据业务接口的调用比例, 采用逐步加压,直接并发方式,获取性能拐点,确认最终压测用户数
监控工具,压测过程中性能指标实时压测监控,服务器监控,被调用链路监控等监控工具,可以了解到各系统之间的调用链路,方便定位性能问题
整理压测报告,备注说明性能问题,需要跟进处理事项,什么时间点优化完再重新复测
压测结束,清理压测数据(设置数据过期时间)
参与人员,运维(支持环境扩容和环境问题解决);研发(支持服务业务梳理,代码问题解决);DBA(数据问题处理,数据库、缓存问题处理);测试(功能业务梳理,性能测试);运营(提供业务数据,配置活动数据)。整个压测过程离不开相关成员的支持和协助
全链路压测开展
1、环境确认
接到压测需求之后,最关键的是要确认目标压测的环境,这个环节非常重要,因为公司决定使用生产环境进行压测,所以当时确定在生产环境上做性能测试,在后续各种准入条件都是要基于生产环境进行准备。
为什么选择在生产环境做压测?
模拟真实用户访问流量
通过公网访问到服务,直接暴露服务依赖之间的调用关系,不会因为环境影响调用
通过模拟真实流量,有利于机器容量得到充分评估
生产环境机器充分且配置较好,可承受最大压测数量,从而推断出生产可承受的最大压力容量
节省重新配置一套压测环境的成本,考虑到压测环境需要与生产环境几乎一样的配置,成本也是不低的
生产环境的版本是最稳定的,不会因为新旧版本而影响功能
节约人力维护成本,按照以往测试经验,在压测环境去部署版本和准备数据,前期准备的时间周期比较长,且需要长期维护,人力成本较高
链路梳理
链路是一个业务的核心,根据业务特性要快速梳理清楚
链路梳理,难点在于服务依赖的边界
示例:首页-》商列 首页跳转到商列,商列服务又会查询商品相关服务数据商列-》第三方服务(简称S) 商列除了查询商品相关服务数据,还会调用到依赖服务S,这里就涉及服务依赖的边界,这也是在梳理链路时必须清楚的。
(1)真实性和可用性:可以从生产环境获取完整数据(历史数据),作为压测的基础数据,通过分析历史数据增长趋势,作为预估判断基准
(2)数据脱敏:生产环境的全链路压测,要考虑到不能对生产环境造成影响和不能影响用户体验等,因此在数据准备时,需要进行数据脱敏
(3)数据隔离:不要污染正常数据,梳理数据处理的每一个环节
提前准备一批压测用户(白名单)
准备优惠券数据(支持多个用户不限制领券次数;判断条件只给特定压测用户领取)
选用特定商品(过滤正式商户商品)
订单数据根据压测用户进行过滤,生成订单数据取消或者删除
(4)在链路的基础上,也有很多的分支业务,而这些分支业务有的需要压测,有的不需要压测,如以下业务可考虑不压测:
给用户下放 push 消息 ,这是定时执行批量任务,可以不用压测,本身push数据量是通过异步队列处理,不是业务接口发起的
短信 ,①短信跟push消息差不多,而且短信收费的,如果压测会产生无数条短信,费用不低;②会产生很多无用的垃圾短信
支付,支付会涉及到调用第三方,可能有人想通过mock数据实现,这也是一种压测方式,但是压测出来的结果跟实际对比肯定是有差异的,涉及生产环境,支付是不做压测的
3、设计数据模型
预估数据模型
通过2/8定律计算吞吐量模型:80%请求数/20%时间=预期TPS
举个例子说明,假设以下数据:
业务量预估模型,根据运营投放的业务量,统计各大促活动阶段的数据模块
QPS预估模型,结合业务预估模型,统计各大促阶段的峰值qps,预估下一阶段大促活动的qps
4、压测平台
(1)jmeter提供分布式压测的方式(压测平台运行模式是调用jmeter内核)、压测数据结合性能监控平台能够实时的收集、可以随时停止压测、一定时间内实时错误率达到阈值自动熔断等。考虑到压测量较大的情况,测试结果异步处理。压测平台提供的能力是发起访问流量。
(2)代码改造:构造白名单用户(压测用户,作为过滤条件),请求打上特殊的标记、随机数等等。因为考虑实际成本问题,没有配置影子库,只能通过特殊标记和压测用户,过滤掉脏数据,以免影响正常运营业务统计。
下单接口带入key:create_xxxxx_xxx_lock_key过滤白名单用户锁定10秒
提供压测分支,修改某个功能的判断逻辑等
5、容量规划
双十一、双十二 大促活动,公司的运营活动,专场活动…… 业务场景复杂,推送数据量大等等特点针对业务场景越发复杂化、海量数据冲击下整个业务系统链的可用性、服务能力的瓶颈,让技术更好的服务业务,创造更多的价值
容量规划的目的,主要是让各业务系统能明确知道:什么时候该加机器、什么时候该减机器?双十一,双十二等大促场景需要准备多少机器,既要保障系统稳定性、又要考虑节约成本。容量规划四阶段:
业务流量预估:通过历史数据分析,设计业务预估模型,预估在某一个时间点业务的访问量会有多大
机器容量评估:初步计算每一个服务系统现有多少台机器,预计需要增加多少机器
机器容量的精调:通过全链路压测手段来模拟大促时刻的用户行为,对各服务系统的容量进行精确调整
流量控制:对各服务系统(目标服务和被依赖服务)配置限流阈值等保护措施,防止实际的业务流量超过预估业务流量的情况下,导致服务系统无法正常运行等
双十一之前,组织各业务技术负责人把相关服务分布,以及服务依赖情况,环境设备的情况进行一系列梳理,统计各业务领域历史高峰数据,进行初步评估。
根据需求计划,把相关业务接口进行梳理,并制定压测场景(性能策略、性能测试方案)和压测计划。
容量二次评估
通过业务,了解大促期间业务量多少(push量),预估qps比现有高峰qps大3-6倍,计算并发预计达到多少?
进行一轮基准压测,收集和统计业务领域峰值qps,再进行综合评估。
进行到 (业务流量预估阶段)、(系统容量评估阶段),我们完成了系统容量的粗略评估,做到这一步还不够,真实的场景并非如此 我们需要做精准的容量规划,给服务做限流降级提供数据参考。
6、场景压测-服务承载能力
获取单台机器的服务能力
为了精准地获取到单台机器的服务能力,压力测试都是直接在生产环境进行,这有两个非常重要的原因:单机压测既需要保证环境的真实性,又要保证流量的真实性
模拟请求:通过对生产环境的某一台机器发起压测请求,以此来计算单机能力,从而达到压力测试的目的
压测工具:压测平台(绑定生产机器host,压测请求指定到目标被压测机器)
选用场景:服务调用量比较大的场景
特点:压测后输出的压测结果非常精准,且不会在其他机器上产生脏数据
负载均衡:Nginx修改负载均衡设备的权重,请求流量指定到单独的被压测机器上
ps:在进行压测的同时,实时探测压测机器的系统负载,一旦服务系统负载达到预设的阈值立刻停止压测,同时输出一份压测报告,通过单机压测获取的单机服务能力值也是容量规划一个非常重要的参考依据
计算公式:最小机器数 = 预估的业务流量量 / 单机服务能力
根据业务数据、评估初步容量和经过单机压测的结果,把各业务领域单独进行峰值压测(性能策略和性能测试方案在前期已经准备充分),采用逐步加压,直接并发方式,获取性能拐点,压测过程各方依赖调用量也会逐步呈现明确的数据。测试场景有单独存在的,也有相互依赖的关系,有以下验证场景:
单接口场景:抽取单接口进行压测,获取接口本身qps,以及单机服务系统承载能力
页面场景:独立页面接口进行归整,把页面请求包含的多个接口组成一个页面场景,其中接口也会有依赖其他服务,形成一条链路,对页面场景压测,主要是评估页面访问流量对服务承载的压力,压测结果基本可以明确各业务场景具体的qps峰值
获取链路压测综合能力
链路场景:把单个接口场景、多个单接口场景和多个页面场景进行结合,按照业务场景划分,根据页面访问量情况:
流量从大到小,对各个压测场景进行调整压测线程数(递增,并发),类似于:首页>商品列表>商品详情>购物车>订单>支付,目的是为了把各服务调用能力进行全面评估。
7、流程注意事项
(1)业务中需要区分流量(正常流量/压测流量)
(2)接收和发送 http / grpc 等请求
在向下游服务发起请求时,增加随机数透传缓存数据
接收到压测流量,使用相应的压测数据
(3)依赖模块
MySQL:备份业务数据,主库从库读写分离,压测数据过滤;压测完成后,清理数据
Redis:同 MySQL
(4)不需要参与压测的做 mock 处理
给用户发push、短信、支付……
8、性能监控及问题定位分析
(1)监控工具
k8s资源监控:k8s群集监控,cpu,网络,pod节点,内存
kvm资源监控:宿主机群集监控,cpu,磁盘IO,网络,内存
访问量集群列表监控:cpu,网络,内存,磁盘IO,JVM,redis……
nlog日志监控:业务领域访问流量,响应时间,请求分布,请求接口
压测实时监控:tps,响应时间,请求数,错误率,错误请求数,请求接口,错误接口
数据库监控:数据库群集监控,主库,从库,读书能力,慢sql,cpu,内存
调用量调整(限流)
问题现象:压测过程qps出现阶段性下降,响应时间阶段性上升
例如:商品服务调用scf服务,scf服务设定调用量是8万/分钟,压测300秒,当商品qps达1400/s左右,scf服务出现4次限流,被限流请求走原逻辑(es查询),可以计算出实际调用量为8.4万/s,要确保商品服务请求量在达到峰值不出现被限流的情况,需要把scf调整量提高到10万/分钟。当商品qps需要达到4000/s,那scf服务调用量至少需要调整到25万/分钟。当然调用量不是越大越好,需要考虑被调用方服务实际的承载能力和机器容量情况,如达不到25万调用量承载能力,应当设定限流閥值。
应用降级
问题现象:压测关键业务场景时,发现存在一些边缘业务的接口
排查手段:梳理边缘业务是否会影响关键业务,跟业务,技术负责人确认,把这些边缘业务接口和功能列出来,在入口处做降级处理
例如:app首页,会调用多个接口,其中有4个接口不是关键功能接口(活动弹窗,订单提示,回收提示,客服),在配置中心增加配置项开关,在压测过程开启和关闭,对比压测,当关闭降级开关,可以明确看到接口会占用主入口流量,除了关键接口数据,4个接口非关键功能接口同样请求到服务会把数据返回
开启降级开关,关键接口调用量明显提升,4个接口只是返回空数据,不会请求到服务
降级的作用是在大促高峰时段,保障应用服务能正常运行,且不影响主功能流程,所采用的应急手段
其他问题
优化前:A服务功能并发压测时,A服务返回响应时间非常慢,当时nginx日志已发出被调用服务的告警信息,查看被调用依赖服务的监控时,发现被调用服务部署(k8s)的实例cpu占用100%,业务功能打开已经有部分出现异常响应。
优化后:k8s扩容3个实例,重新压测 A服务功能,没有出现响应时间很慢的情况,被调用服务的cpu保持在40-50%之间,没有出现100%的情况
应用逻辑抽离(代码改造)
P服务接口,每次请求qps比较低,与研发一同分析代码逻辑,接口每次查询都会查询商列数据,经讨论计划把代码进行改造,把查询商列数据的逻辑业务抽离,再进行对比压测。
老版本接口,逻辑会查询所有商列数据
新版本接口,抽离业务逻辑,商列数据不查询
老版本走老逻辑全部逻辑查询在一个接口实现,新版本抽离部分查询逻辑,新增另外的接口查询,降低接口查询压力
性能问题肯定不止以上几个,还有缓存过期问题,缓存命中率问题,缓存穿透问题,数据库磁盘打满,分布式锁等等,具体的问题就不一一列举啦。
9、数据清理
压测用户(白名单):不能出现在真实业务当中,压测结束,会把这批用户全部过滤被禁用
优惠券数据:设置过期时间,压测结束后,通知运营过滤券数据
特定商品:创建自营商品,不能影响正常业务使用,压测结束后,商品下架
根据压测用户过滤订单数据,把订单数据取消或者删除,过滤用户订单数据,不影响正常业务量统计
10、测试结果
经历双十一大促全链路压测,大大小小性能优化近50次,其中关键问题有:服务cpu达100%需要机器扩容,业务逻辑代码改造,增加缓存策略,服务依赖优化,数据库连接异常,dns解析失败,ES查询阻塞等等,其余优化问题不一一列举,性能测试总会遇到意想不到问题,核心问题提前发现并得以解决,也是为下次大促做保障。
而双十二大促压测有了双十一大促压测作为基础,核心问题提前规避和检查,在全链路压测过程中除了存在部分服务cpu占用100%问题和缓存问题,影响核心业务的性能问题基本上没有出现,有的只是边缘业务问题,不影响主业务流程。
对于双十一、双十二这类大促活动,全链路压测必然是保障核心业务稳定性的保障手段之一。