性能测试体系建设演进之路
题记
今年是我个人从事软件测试工作的第六个年头,职业生涯至今经历了功能-接口-自动化-性能测试岗位的变迁。
18年下半年开始以团队owner的角色进行工作开展,不过当时团队技术体系建设已经步入正轨,对我个人而言,并没有太多沉淀。
19年跳槽后,有幸从零开始主导我司的性能测试体系建设工作,个人之前的很多想法得以落地实现。
这也许是除了薪资之外,对我个人而言获得的最大成就感。。。
导图
演进
基础建设
1、文档建设
前段时间知乎回答了一个问题:做技术人是不是都反感写文字类的东西,比如需求文档,需求分析等等?之前的博客也写过类似的内容:性能测试从零开始实施指南——文档建设篇。
我个人认为无论是作为个人学习笔记抑或一个Team的累积沉淀,文档建设的工作必不可少,而且是重中之重。原因如下:
1)降低“口头说明”带来的风险;
2)文档是很重要的记录和交流介质;
3)便于事前、事中、事后快速回溯追踪;
4)降低工作交接、沟通的成本,提高效率;
5)文档是一次梳理思路,review的方式;
6)文档是很重要的工作产出,自我价值诉求的重要手段(KPI);
当然,现在有很多在线协同文档工具,如confluence、语雀(参考-工具汇总)。我司性能团队文档类目如下:
2、资源管理
这里的资源主要指压测资源,包含如下几项:
1)压测机
2)压测场景
3)压测脚本
4)压测数据
无论是平台化还是基础的命令执行,其中要考虑的因素还是很多的,比如:
脚本命名规则:以接口名命名,见名知意;
文件命名规则:以参数类型、字段名命名;
权限管理:性能测试同学可以赋予root/s-user权限;开发&业务测试同学可以赋予ops/onlyread权限;
路径管理:按照服务器的访问权限&路径命名,比如:
压测脚本路径:ops/perftest/script/transcation/order/ordercreate.jmx
压测数据路径:ops/perftest/data/transcation/order/productId.csv
PS:如上命名规则和权限路径,以jmeter命令行启动场景为准,平台化可通过配置文件统一自定义。
3、环境建设
我个人强烈建议有一套独立的压测环境,这样既能做到和业务测试互不干扰,压测的结果相对来说也更贴近真实的场景。
考虑到成本和维护等因素,压测环境建议按照具体情况来配置,主要遵循如下几条原则:
1)机器配置和生产保持一致;
2)机器数量和生产进行等比缩容(可以同配置最小化,即1台机器1个服务);
3)网关和注册中心&配置中心可以集群部署(按照流量大小);
4)支持自动扩容、监控告警等功能(需要基础技术建设到一定程度,比如:发布&监控平台支持)
PS:上述原则,基于微服务架构!
4、技术选型
技术选型主要考虑如下几个方面:
1)压测工具:接入成本、学习成本,重点是快速产出有效直观的价值!
2)监控工具:监控工具要考虑到性能损耗、接入难度、全面性、易用性;
3)数据工具:包括造数工具、数据存储、解析等方面;
4)分析工具:主要指的是问题分析工具,比如JDK自带的JVM Profiler;
规范制定
技术体系建设中,规范的重要性不言而喻。在性能测试中,比较重要的有如下几条规范:
1、需求发起
性能是一种需求!需求从何而来,如何发起,准入准出条件,必须优先界定好。思维导图:
2、需求评估
在性能需求评估中,主要考虑如下几点:
1)可行性(必要性)分析;
2)收益率评估(投入/产出-ROI);
3)约定关键时间节点,如提测、deadline;
4)统一重要指标口径,明确预期指标(业务&技术);
3、资源排期
这里的资源主要指人力资源、时间窗口以及机器资源,对于一个team来说,资源排期很重要!
4、指标度量
这里的指标并非压测数据指标,而是从部门/Team角度长期来看,需要考虑的指标,主要参考如下几点:
1)成本:测试前后,机器成本降低了多少;
2)数据:每迭代/版本,服务/链路性能提升占比;
3)效率:每个阶段,准备/部署/测试耗时降低了多少;
4)输出:团队/部门内部技术分享、性能宣讲、质量意识提升比;
5)质量:每统计区间,线上服务可用性/稳定性提升比、故障率下降比;
6)赋能:每月/季度,业务测试团队性能测试工时/需求接入/技能提升占比;
5、测试方案
测试方案的规范,可以视公司研发文化、team大小、具体情况来制定。当然,制定一个规范模板还是很有必要的,这样不仅能对工作给出一定的指导方向,还便于其他干系人能快速了解。
参考:简易性能测试方案模板
6、测试报告
同测试方案一样,测试报告的规范模板也是很有必要的,同样可以对工作给出指导方向。
参考:简易性能测试报告模板
需求周期
1、调研评估
接触了很多做性能测试的同学,聊下来,发现部分同学对性能需求的可行性评估,依然不太明白为什么这么做。如上文所说,在性能需求调研评估过程中,要注意的几点分别如下:
1)可行性分析:即业务场景、该场景的技术实现方案、用户特征等,是否有必要开展性能测试;
推荐阅读:认清性能问题(Thinking Clearly about Performance)
2)收益率评估(ROI):开展性能测试的成本,包括时间、人力、机器环境成本,以及技术改造成本;
3)约定关键时间节点,如提测、deadline:这样做的好处是能根据测试时间窗口更好的评估测试工作的安排,知道什么时间做什么,区分优先级很重要。
4)统一指标口径,明确预期指标:比如双11大促,技术指标包括:日常线上峰值流量、机器负载、预估流量递增比率、扩容速率、consumer group、告警阈值等;
而业务指标包括:预计GVM、活动场次时间、优惠券类型数量、订单量等指标。明确这些数据后,才能更好的评估需求,进行压测方案设计。
2、需求排期
需求排期的重要性不言而喻。如何在有限的资源下尽可能提高需求的吞吐量,除了个人工作效率、团队协同能力之外,良好的资源评估和任务分配是很重要的影响因素。
3、准入准出
无论是过早还是过晚的考虑性能问题,都会是一场灾难!
过早考虑不确定性较多,太晚的话,优化成本及风险又太高,因此,选择合适的时机开始,是很重要的。
性能测试切入时机,是个玄学,需要考虑需求类型、具体场景、资源、时间、优先级等很多因素。但一般来说,还是有适合大多数场景的参考原则,列举几项供参考:
1)普适性原则-功能测试提测阶段切入;
2)特殊性原则-电商双11,最少提前2个月准备;
3)迭代性原则-二轮测试开始时切入;
4)新服务原则-prd&技术review阶段切入;
数据管理
数据管理是性能测试中很重要的一环,无论是数据量级、分布方式、是否缓存、缓存大小还是热点数据,都是需要考虑的地方。
还有一点经常被忽略的,是数据多样性引起的覆盖率问题。性能测试中,主要有如下几种类型:
1、基础数据
对于性能测试来说,基础数据一般指的是支撑业务流程正常运行所必备的数据,需要考虑如下几个方面:
1)数据量级:根据环境具体配置信息,保证数据量级和生产环境等比例,是很有必要的事情;
2)数据脱敏:从经验来说,基础数据的量级一般较大,常见的准备方式都是copy生产数据并进行脱敏;
2、测试数据
测试数据是为了满足被测业务场景的链路而所需的数据,在具体的压测准备阶段,需要根据被测链路,针对性的准备测试数据,保证场景的正常执行;
3、唯一性数据
某些比较特殊的被测场景,所需的数据是具有唯一属性的,或者一次性使用的特性。
从经验来说,这类数据,建议通过走正常的业务逻辑去生成,可以根据所需数据量大小来准备。
4、参数化数据
这类数据一般是具有可复用性的,比如productId/userId...,建议提前了解整体的业务和技术类型,准备一批量级较大的数据,避免重复工作。
问题追踪
1、问题记录
针对压测过程中发现的问题进行分类记录汇总,是很重要的一件事。优点如下:
1)问题追溯
2)工作产出
3)输出规范手册
PS:性能缺陷分类参考
缺陷类型 | 缺陷描述 |
硬件 | 磁盘空间 |
CPU | |
IO读写速率 | |
内存 | |
网络 | 带宽 |
网络波动 | |
CDN | |
延时 | |
丢包 | |
应用 | JVM |
代码逻辑 | |
配置 | JDK版本 |
底层配置 | |
参数配置 | |
数据库 | 索引 |
锁 | |
表空间 | |
慢SQL | |
数据量 | |
中间件 | 超时 |
线程池 | |
缓存策略 | |
最大连接数 | |
通信实现方式 | |
负载均衡 |
2、生命周期
性能问题的生命周期,和功能BUG一样,这点技术同学应该都懂。
3、方法输出
影响性能的因素有很多,但绝大多数的性能问题都是由于配置、参数、代码逻辑的问题导致。
通过对性能问题的分类记录汇总追溯,可以总结出一些比较通用的参考规范,类似《阿里巴巴java开发手册》。
常见影响性能的因素及优化建议如下:
1)日志打印:降低日志输出level,减少IO消耗;
日志打印建议移除json序列化操作;
关闭状态机内相关日志,添加开关,大促时关闭;
出参过多情况下,封装处理,只打印需要的核心参数;
避免统一日志处理的apo拦截,建议移除所有主动拦截,需要的地方添加注解;
2)缓存使用:针对不易发生变动/变动影响较小的调用添加缓存/数据快照;
3)调用方式:对于一些聚合类的接口调用,建议串行改并行/异步调用;
4)线程配置:隔离各接口使用的线程池,防止长短尾拖垮线程池;
为了防止网络抖动,建议线程数按照(CPU可用核心数/(1-阻塞系数)*2)配置。
worker-threads、maxConnections、ConnectTimeout、ReadTimeout等参数无需过高;
5)重复调用:微服务间的调用存在方法调用冗余情况,应尽量避免;
6)等待队列:根据等待队列长度算法来说,建议队列长度根据可接受的最长时间来配置,比如:
接受最长时间500ms,超过500ms还不能处理丢弃。已知正常rt25,每个线程500ms可以处理20个等待队列内的请求,
假若有16个线程,所以等待队列长度设置为320。队列过长无意义,无法新增非核心线程,且持续恶化处理速度。
监控体系
监控体系的构建,是一个长期迭代的过程,很考验基础技术建设的能力和程度。
除了压测本身所需的指标监控,还需要对被测服务的资源耗用(基础监控)、链路调用关系(链路监控)以及各种中间件进行监控。
1、压测监控
基于jmeter+influxdb+grafana搭建的压测监控大盘:
2、基础监控
基于Prometheus技术体系搭建的基础指标监控大盘:
3、链路监控
目前业界内链路监控工具还是蛮多的,而且开源的也不少,足以满足日常所需。比如Cat、Jaeger、Zipkin、Pinpoint、Skywalking等。
下图为Jaeger的链路追踪界面:
4、中间件监控
中间件监控,涉及的组件较多,比如redis/MQ/Kafka/DB等,上面提到的链路监控工具,实际上对中间件的监控支持还算不错,当然,各有优劣。
需要哪些指标,告警阈值如何设置,还是按需所配吧。
报表输出
报表对于一个team来说是很重要的工作量化产出!
1、轮次小结
一般来说,性能测试要执行多轮的测试验证,针对每轮结果进行直观的比较验证,无论从效率还是信息同步方面,都是很有帮助的。
2、数据归档
这里的数据归档,包含需求吞吐量、完成质量、遗留问题、压测结果等很多数据。
我们目前的做法及规划如下:
1)需求/问题归档:写入mysql,通过定时job扫描,并定期拉取数据进行不同维度的聚合计算,CC干系人。
2)压测数据归档:写入Influxdb,并提供查询API给到度量平台来聚合数据,做其他维度的报表展现。
3、性能基线
属性 |
说明 |
目的 |
作为衡量版本迭代的一个质量维度系数,更全面的衡量每版本的交付质量 |
衡量维度 |
1)每版本性能基准;2)长期性能变化趋势(季度/年度) |
执行方式 |
每版本迭代对核心链路进行覆盖执行,采用回归测试策略 |
执行时间 |
二轮回归开始→发布预发之前 |
性能基线的建立,有以下几点需要注意:
1)定义基准:包括术语、维度、范围、指标等信息的统一说明;
2)基准数值:个人建议可接受降幅原则上≤5%;
3)跟踪方式:性能变化的跟踪方式,和上述的衡量维度类似,分短期和长期,时间区间可自定义;
4)实施说明:包含执行的时间、范围、具体方式、准入准出条件,该任务最好具体到人;
5)前置条件:核心链路梳理、初始版本基准数值确认、环境/压测机/权限分配/路径/脚本/数据;
PS:如何追踪、如何统计并聚合计算,根据team情况和具体情形自行确定!
4、容量规划
容量规划是一个长期建设的过程,目前我司也是规划中,具体如何开展,什么时候开展,有哪些方法论,业内目前并没有一个普适性的方法论。
可以参考我之前的一篇博客:浅谈容量测试与容量规划
赋能开源
我个人认为,性能是一个团队所必需具备的能力和特质,并不是少数专职性能测试同学才能做得事情。
在基础的技术建设和性能测试成熟度到一定程度时,可将部分压测相关工作&权限赋予业务测试和业务研发团队,这样不仅有助于工作上互相了解,
更能提高整个团队的能力,性能测试同学也可以抽出更多时间在稳定性保障工作上,而不是写个脚本压测下,就完事的重复工作。
更多阅读:当我们讨论性能测试时,我们在说什么?
团队沉淀
要想不断提高团队的技术、沟通协同、解决问题能力,团队升级是需要时刻考虑的。
只有不断提升团队整体的能力,个人的能力才会更快的提升。一般来说,常见的方式有如下几种:
1)技术累积:前面说的文档建设就是个很好的方式,还可以输出技术白皮书等内容;
2)内部培训:建议定期开展,一般每个月固定开展一次,包括技术、业务、经验和教训;
3)团队分享:指的是包含整个研发部门甚至整个公司的跨团队分享,还是建议积极参与;
4)公开沙龙:当团队规模,技术累积等到了一定程度,可以对外举行技术沙龙,进一步提升技术影响力的同时,也是一个很好的锻炼个人能力的方式。有输入有输出,才能有所得;
5)技术大会:每年都有很多的业内技术大会,可以挑选具有一定影响力和知名的行业大会,在团队里挑选部分优秀的同事参加,然后分享,这也是一个促进团队凝聚力的方式。