资讯详情

资讯详情

性能测试入门实战:核心指标与瓶颈定位指南

性能测试这个事很多人一听就觉得“高大上”总觉得是专门搞性能优化的大牛才碰的。但真进了这个圈子你会发现性能测试更像是体检不复杂但特别考验耐心和思路。刚入行的时候我也一头雾水光看那些术语就够懵的响应时间、TPS、并发数、P99、毛刺、长尾……每个词好像都见过连在一起就不知道在说什么。这篇入门篇我就完全放下理论书的架子用实际操作遇到过的情况来讲。先讲清楚性能测试到底在干嘛再拆开核心指标接着给你一条从需求到报告的完整执行路径最后落回工具和避坑经验。不管是刚转岗的新人还是被临时抓来做压测的研发按这个思路去动手至少不会跑偏。1. 性能测试到底在测什么很多人第一次接触性能测试是想知道系统能不能扛住双十一、秒杀这类活动。但真上手会发现性能测试不是简单开个压测工具猛打一顿它背后是一套完整的目标分解业务想保证什么用户能接受什么系统瓶颈卡在哪。1.1 别把性能测试等同于压力测试最开始我犯过一个典型错误就是把“性能测试”和“压力测试”画等号。实际上性能测试是一个大类底下至少能分出五种常见类型负载测试模拟预期的日常访问量验证系统在正常负载下是否满足指标比如每秒两百个请求时响应时间是否稳定。压力测试不断往上加并发或请求量找到系统的极限拐点看它在超出预期负载时是性能缓慢下降还是直接崩溃。稳定性测试持续跑几小时到几天验证长时间运行下有没有内存泄漏、连接缓慢耗尽这类慢性问题。峰值测试模拟突发的集中流量冲击比如整点秒杀、活动开启瞬间验证扩容和限流手段是否真的能兜住。容量测试为了回答“再加多少用户就撑不住了”或者“当前资源能支撑多少业务量”通常和数据增长一起做。区分这些不是做文字游戏。因为不同目标对应的场景设计差别很大负载测试关注稳态压力测试关心极限稳定性测试要延长持续时间。如果你拿压测的思路去做稳定性测试跑个五分钟就收工内存泄漏根本看不出来。1.2 性能测试到底解决什么问题抛开术语性能测试就回答四件事系统快不快系统稳不稳系统能扛多大流量以及流量到了之后最先撑不住的是什么。第一件事“快不快”看响应时间这个最直观。第二件事“稳不稳”看波动。很多系统平均响应时间很好看但运行一段时间后经常冒出一两个特别慢的请求这就比稳定在某个偏高值更危险。第三件事“能扛多大流量”就是常规的容量评估。第四件事“先撑不住什么”最有价值因为性能测试的真正产出不是那些跑分数据而是瓶颈清单是数据库先到极限还是线程池先耗尽或者是某个第三方接口拖后腿。我之前做电商系统测试时压测一开始发现吞吐量完全上不去监控一看CPU占用率早早就满了但业务服务的CPU其实不高反而是日志组件的序列化逻辑把CPU吃干净了。如果不拆分指标只盯着“系统扛不住”这个结论现场排查能浪费一下午。1.3 性能测试真正要盯的目标入门最怕的是拿到需求就开压压完导出报告发现响应时间超标、TPS不达预期却不知道问题出在需求本身还是场景设计错了还是系统真不行。我建议拿到任何性能需求先拆成三层业务层用户可接受的最长等待时间是多少核心操作有哪些流量高峰持续多久。接口层哪些接口被高频调用调用比例是多少读写占比是多少。资源层当前部署有多少台机器每台机器配置如何数据库连接池、线程池这类基础参数有没有预设上限。这三层拆清楚性能测试才算有了骨架。否则你测出来的结果只是一个“当前系统在某条件下表现如何”的状态记录跟业务判断完全脱节。特别是接口占比很多新人测试脚本常常只压一个核心接口忽略了实际场景里读多写少、或者多个接口串联的调用链结果测出来的容量跟线上真实情况相差巨大。2. 核心指标和术语先迈过这个坎性能测试入门第一道坎就是指标。很多测试报告里列了一堆数字但没有哪个数字是真正需要决策的。我们不需要懂全部但下面这几个核心指标必须能说清楚它的含义和局限。2.1 响应时间平均值不可信要看分位数响应时间就是客户端发起请求到收到完整响应之间的时长通常以毫秒为单位。但这里有个大坑平均响应时间的说服力非常差。假如有十个请求九个是10毫秒一个是910毫秒平均值就是100毫秒看起来还行但实际上已经有一个请求慢到用户要骂人了。所以现在业界更看重百分位数。P95的意思是95%的请求响应时间都小于等于某个值P99则是99%的请求都达到了某个水平。看这两个值能很好地捕捉“长尾延迟”问题也就是少数请求特别慢的情况。我自己的习惯是P95用于日常体验监控P99用于线上核心链路兜底平均值只在说明整体趋势时拿出来参考。响应时间还要注意一点前端用户感知的响应时间和后端接口耗时不是一个概念。用户眼睛里的“慢”可能包含网络传输、静态资源加载、浏览器渲染等多段时长。性能测试通常聚焦后端接口耗时但不要拿后端数据直接充当用户体验时间中间差着一截呢。2.2 TPS、QPS 和并发数以及那条万能公式TPS 是每秒事务数QPS 是每秒查询数。两者很相似但事务可以是一个完整的业务操作比如“提交订单”一个事务可能包含查询库存、锁定库存、生成订单等多个内部请求QPS 则更偏单次查询请求。对于大多数入门场景先按“请求/秒”理解就行不用过度纠结差异。并发数指的是同一时刻系统内正在处理的请求数量它不是每秒能支撑的请求总数。这两个概念常被混淆。用一条公式可以串起来这个公式在性能测试里非常有用并发数 响应时间秒 × TPS每秒事务数这条公式叫做利特尔法则。举个例子如果一个接口平均响应时间是0.5秒我们希望它每秒能处理200个请求那么系统至少要能同时容纳100个在途请求。这100就是必须达到的并发承载量。反向也能用压测工具报告显示平均响应时间为0.5秒TPS是200那系统中同时处理的请求数量就大约是100个。理解这条公式最大的价值是让你判断一个系统的并发能力是否合理。很多时候业务方开口就是“我们要支持一万并发”你算出实际每秒请求量后发现系统设计目标和流量预期完全不在一个量级上这时候就得回去对需求。2.3 错误率、资源使用率也不能只看表面错误率指的是失败请求占总请求的比例通常压测时会要求错误率低于0.1%甚至更低。这里要提醒一句压测时错误可以分为业务校验失败、超时、连接被拒绝、HTTP异常等很多种拿到错误数据后最好看下错误分类不然可能把“参数不合法”造成的业务异常当成系统故障处理白排查半天。资源使用率主要关注CPU、内存、磁盘I/O、网络带宽。资源使用率不是越低越好也不是越高越糟关键是看谁先到瓶颈。如果你的压测过程中CPU只有30%TPS已经上不去了说明瓶颈不在CPU可能在数据库连接池、线程池、锁竞争等地方别一门心思扩CPU。内存指标还要注意JVM堆内的GC情况老年代频繁回收往往比整体内存用量升高更能说明问题。磁盘I/O要区分读写比例顺序读写还是随机读写表现差异非常大。网络带宽同理压力机和服务器之间的带宽瓶颈会让你误判系统性能已经被压垮。2.4 一张表看懂指标目标怎么定从零起步做性能测试最常问的就是“我的指标定多少合适”。没有标准答案但是可以给一个参照模板拿到具体项目后按实际情况调整。指标维度目标参考备注平均响应时间200~300 ms核心接口尽量控制在200 ms内P95响应时间500 ms以内用户体验敏感操作参考值P99响应时间1秒以内核心链路兜底值TPS根据业务峰值×1.5倍预估高峰流量的1.5倍留缓冲错误率小于0.1%需排除业务参数错误CPU使用率70%~85%持续高于90%往往伴随排队内存使用率小于85%尤其注意是否存在持续增长磁盘I/O使用率小于70%超80%易出现明显抖动尤其要提醒的是上面的数值是通用参考不是行业标准。不同业务场景差异很大一个报表查询接口响应时间一两秒可能都能接受但一个登录接口超过了300毫秒用户就会觉得卡。指标必须结合业务容忍度来定否则测出的数字再漂亮也没有实际意义。3. 入门必看完整测试流程实录掌握了指标概念就进入最实操的部分一个完整的性能测试项目应该怎么推进。很多新人拿到任务直接打开压测工具开始填参数这是最常见的不规范做法。我按自己的习惯整理一条执行路径每个环节都能落地。3.1 需求分析从业务场景到测试场景第一步看起来“虚”但决定了整个压测方向。你需要搞清楚几个问题被测系统的核心业务是什么一次完整业务操作要经过哪些服务流量从哪里进、往哪里出高频接口比例如何。举个例子我在实际项目中测过一个订单系统从表面看核心接口是“提交订单”但如果只压这单接口结果没有参考价值。因为订单提交会先调库存、再调用户积分、最后落库还涉及消息队列异步通知。需求阶段就要把这些链路画出来搞清楚每一次用户操作对应多少个后端调用调用比例是按什么逻辑分布的。这个阶段还要确认环境差异。测试环境是不是和生成环境同配置数据库数据量是不是接近线上有没有任务调度在压测期间抢占资源。有一回测试环境搭建好开始压测一跑就发现TPS剧烈波动查了半天才发现环境里混了一个定时任务在每个整点批量跑数据清洗直接造成资源抢占。需求分析阶段把这些因素排掉后面会省心很多。3.2 测试数据设计冷热数据分开数据量要足够性能测试里的“数据”是个大坑。数据的数量、分布、状态都会直接影响测试结果。先说数据量。数据库里如果只有几百条记录查询走索引一两毫秒就返回但线上已经上亿条数据同样的SQL执行计划可能就完全不同。所以压测前要评估线上数据规模测试环境至少要造出接近量级的数据。造数方法可以用存储过程批量生成也可以直接脱敏后从线上导入关键是保证主要查询条件下的记录分布和线上接近。再说数据状态。订单状态是不变和变化的。如果要压测一个“查询待付款订单”的接口测试库里不能全是已付款订单必须按业务比例造好待付款、已付款、已取消等状态。有些新手用一个用户反复下单压测随着测试推进数据状态不断变化后半程的结果就和前半段不可比了。冷热数据和脏数据也要考虑。压测时尽量不用已知无意义的数据比如全是同一条测试SQL反复执行会导致数据库缓存命中率畸高测试结果偏高。真实场景中数据访问有明显热点分布有冷数据热数据之分。如果条件允许用线上脱敏数据集是最稳妥的。3.3 测试模型与实施加压方式不是拍脑袋压测场景设计最常用的加压方式有几种并发数逐步递增、单位时间内请求速率阶梯递增、直接按目标TPS恒定维持压力。新手最容易犯的错误是刚开始就压满目标值导致系统直接被打蒙拿到的结果无法判断是从一开始就扛不住还是到某个临界点才劣化。我推荐的做法是阶梯加压。比如计划压到每秒五百请求那就先以每秒五十请求起步跑两三分钟观察各项指标稳定后再加到每秒一百继续观察直到目标值每个梯度之间留足观察时间。这样做至少有三个好处能定位性能拐点的具体位置能发现系统何时开始出现长尾延迟也能避免一次性压力过大直接拖垮服务。并发线程数在压力机端怎么设也很讲究。很多人以为并发数就是线程数设个一万才有冲击力但每台压力机的线程数和系统的线程调度开销会形成额外压力。我一般习惯先跑一个小批量预热看响应时间和TPS的对应关系用利特尔法则估算合理并发数再决定正式压测的并发梯度。3.4 结果记录与分析报告里到底该放什么压测执行完报告里不能只丢两张截图。一份能真正帮助排查问题的报告至少要包含以下内容测试场景描述包括接口路径、压测时长、数据准备方式。压力模型说明比如梯度从多少到多少每阶段持续多久。指标数据曲线最好同时展示TPS、响应时间、错误率和资源使用率并且把时间轴对齐。瓶颈观察记录比如某个时刻CPU达到90%、响应时间从200毫秒飙到800毫秒对应的排查动作是什么。结论和下一步建议比如是否需要扩容、是否需要调参、是否需要新增索引。特别要强调时间轴对齐。一个常见的分析错误是把TPS下降和CPU升高看成分开的趋势其实它们往往是同一件事的两面。你把TPS曲线和响应时间曲线叠在一起看如果响应时间升高但TPS没有掉说明系统在排队如果TPS下降且资源使用率也下降说明系统在等待某个下游资源。单纯给结果数字不给趋势是在“算命”不是在分析性能。这里还要提一句监控。压测期间最好同时抓应用日志、数据库慢日志、GC日志、中间件监控。把所有监控的时间粒度统一一般建议5秒一个采集点如果粒度是分钟级很多毛刺会被平均掉关键问题根本看不出来。4. 工具选型与脚本实现的细节再往后就是工具落地。性能测试工具很多没有绝对最好的只有适不适合你当前场景。我把自己用过的几个主流工具做个对比然后重点讲脚本编写中那些真正影响结果准确性的细节。4.1 主流工具怎么选不吹不黑的对比开源的性能测试工具常见的有JMeter、Locust、k6、wrk、Gatling等。它们不是一类东西适用场景差异很大。工具协议支持脚本方式分布式压测学习成本适合场景JMeterHTTP、JDBC、JMS等GUI配置为主支持中复杂业务场景、多功能测试LocustHTTP/WebSocket等Python代码支持中低需要灵活编写压测逻辑k6HTTP、gRPC、WebSocketJavaScript脚本支持低开发人员日常压测、CI集成wrkHTTPLua脚本有限低快速探测单机接口性能我的经验是如果只是临时想知道一个接口的性能上限用wrk这类轻量工具最快一条命令就能跑起来。但如果要模拟完整业务链路、需要参数化多类用户数据、还要生成规范报告JMeter依然是团队协作中最稳的选择。Locust适合希望用代码管理压测脚本的团队k6则非常适合做流水线里的自动化回归。很多人纠结工具选型其实没有太大必要。工具只是施压手段真正宝贵的是你对业务场景的理解和对结果的分析能力。工具换起来很容易思路换不了。4.2 JMeter初体验一个最小可跑的脚本我用JMeter举个例子因为大部分人入门接触的第一个工具就是它。一个最小脚本只需要六步创建测试计划设置一个线程组。在线程组里配置线程数、Ramp-Up时间、循环次数。添加HTTP请求采样器填写协议、服务器地址、端口、路径。添加HTTP头管理器带上必要的Content-Type和鉴权信息。添加查看结果树和聚合报告监听器。先跑一个单线程验证脚本正确性再加大并发执行正式测试。很多新手一上来就加很高的线程数然后直接把聚合报告打开结果发现响应时间波动大得离谱。正确姿势是先以1个线程、循环1次走通请求确认状态码正确、响应内容符合预期再逐步加压。Ramp-Up时间的意义是控制线程启动的速率。比如线程数设100Ramp-Up设100秒那就是大约每秒增加1个新线程。这个参数让压力逐步建立而不是瞬间把100个线程全打上去。入门阶段我建议Ramp-Up时间不短于线程数的一半给服务一个预热期。4.3 脚本不能“打架”参数化、关联和断言脚本里最容易出问题的三个地方就是参数化、关联和断言。这三个没处理好压测结果基本不可信。参数化解决的是“不同请求用不同数据”的问题。真实业务里每个用户的账号、商品ID、订单号都不同压测脚本如果把某个商品ID写死会让缓存命中率虚高测出来的结果失真。JMeter里可以用CSV数据文件配置参数按行读取不同用户数据也可以借助函数生成随机值。关联解决的是“后一个请求使用前一个请求的返回值”的问题。典型场景是登录后拿到token然后带着token访问业务接口。如果脚本写死一个登录token压测过程中token过期后后面的请求将全部失败错误率直接飙高这种错误很容易让人误判系统有问题。解决方案是用正则表达式提取器或JSON提取器把前一个接口返回的动态值取出来放入后续请求的变量中。断言解决的问题是“请求成功不等于业务成功”。HTTP响应的状态码是200不代表订单真的创建成功了。可能在业务层面上返回了“库存不足”这类错误提示但HTTP层依然是200。所以压测时至少要加一个响应断言检查关键业务标识是否存在于返回内容中把真正的失败识别出来。NULL是一个很关键的细节。脚本里面如果有未定义的空值请求发送时会自动带上“NULL”这样的字面量后端解析成字符串轻则参数校验失败重则产生脏数据。建议在执行较大并发前先在日志里抽查几条请求参数确认数据完整。4.4 脚本层面那些容易忽略的细节讲几个压测脚本的细节这些坑我都踩过不止一次第一HTTP头里的Content-Type必须和请求体格式匹配。比如POST一串JSON数据但Content-Type是application/x-www-form-urlencoded后端可能解析不到参数接口直接返回参数错误。第二Cookie管理要单独处理。如果被测系统依赖登录态脚本要用HTTP Cookie管理器维持会话不是每次请求重新登录也不是完全不带Cookie后者会让请求全部落在登录校验上压出来的结果完全不是业务接口的真实性能。第三时间戳参数要注意唯一性。很多接口用当前时间戳做防重校验如果压测时每秒钟生成的时间戳没有变化后续请求会因为重复而被业务层拦截错误率奇高。第四压测机自身性能也会成为瓶颈。当请求量极大时压力机要处理大量并发socket、日志输出和结果采样。JMeter的这种情况下不要开太多监听器尤其是“查看结果树”在压力期间会消耗很多内存。建议压力测试期间只保留必要的采样数据或者关闭结果树和聚合报告监听等压测结束再重新生成报告。5. 性能瓶颈定位与常见问题如果说前面都在讲“怎么测”那这一步就是讲“测出来之后怎么办”。性能瓶颈定位没有玄学就是一层层剥开。我总结了一套入门能直接套用的排查思路再附上几个真实场景。5.1 瓶颈定位的基本套路由外到内拆解遇到性能不达标先不要一头扎进代码。我习惯按这个顺序排查先看压力机一侧是不是压测机本身资源耗尽导致发压不准。再看接入层网关、负载均衡的连接数有没有达到上限有没有超时等待。再看应用层应用服务的线程池、连接池是否耗尽GC有没有异常。再看数据库和缓存数据库CPU、慢查询、锁等待缓存的命中率和过期策略。最后看外部依赖第三方接口、消息队列消费速度是否成为隐性瓶颈。每一步都要有监控数据来验证不能靠猜。最典型的反例是一看到响应时间变长就直接加服务器结果加完毫无变化后来发现瓶颈是数据库连接数固定连接池早就满了应用扩容根本没意义。这里分享一个判断技巧如果TPS上不去但应用CPU和内存都很空闲大概率是等待下游或者锁等待如果应用CPU已经打满说明瓶颈在应用内部的逻辑处理或垃圾回收。前者往连接池、慢SQL、下游接口方向查后者往代码热点和GC日志方向查方向对了排查就快了一半。5.2 典型问题实录和解决思路我挑四个高频瓶颈场景每一个都拿真实遇到过的情况来说明。第一个是数据库连接池占满。现象是压测刚跑几分钟TPS开始下降应用日志里大量报“获取连接超时”数据库端监控却显示数据库负载不高。原因通常是应用层的数据库连接池配置过小或者每次操作没有正确释放连接。注意这种情况不能盲目扩连接池因为每一个连接都占用数据库端资源池子开得太大反而会把数据库打垮。正确做法是先看应用日志里是否有连接泄漏同时检查慢查询和长事务再把连接池上限调整到合理值。第二个是GC频繁导致响应时间锯齿。现象是平均响应时间还好但P99一路走高响应时间曲线呈现出规律的锯齿状。应用CPU不算高但监控发现Full GC频繁。这种情况多见于堆内存设置过小或对象分配过多。先看GC日志确认频率再通过内存分析工具抓对象分配找到大对象产生的源头。压测前适度调整堆大小能缓解但不解决根本问题。第三个是CPU高但系统却空闲。现象是业务服务的CPU接近满载但TPS依然很低数据库端也完全没有压力。这通常意味着应用内部有大量计算浪费比如循环里做字符串拼接、日志框架在压测级别下疯狂输出、序列化解析特别重。我曾经遇到一个性能差到极点的接口一对日志服务端每分钟输出几十万行调试日志磁盘I/O和CPU都被日志吃掉了关掉调试日志后TPS直接翻了数倍。第四个是负载不均导致单台机器被打穿。压测环境中前面挂了负载均衡但请求分发策略是IP哈希并发压力都集中到其中一台机器上。现象是某台应用服务器CPU打满其他机器处于低负载。排查时先看每台服务节点的监控数据是否均衡再检查负载均衡策略是否符合压测模型要求。有时候模拟的都是同一个负载机发起请求IP哈希会把所有流量定向到同一节点这时候需要调整负载均衡策略或让压测机使用多个来源IP。5.3 快速排查速查表把常见问题整理成速查表现场排查直接用。症状可能原因初步验证方法TPS低且应用CPU低数据库连接池耗尽查看连接池监控和“获取连接超时”日志TPS低且应用CPU高代码热点或GC抓线程快照、查看GC日志P99高但平均值正常长尾延迟分析分位数曲线排查锁竞争和大对象错误率突然飙升参数化失效或token过期查看错误类型确认关联是否失效响应时间锯齿状波动定时任务或GC叠加时间轴核对定时任务执行点网络吞吐上不去带宽限制或小包问题查看网卡监控确认带宽打满状态压测结果不可复现测试数据变化或环境混跑固定数据快照清理占资源任务这张表只能当线索真正定位还得靠数据和代码结合。性能问题的原因经常是多个因素叠加排查时别急着下结论每个假设都要拿监控数据验证。6. 我的一点实操体会和忠告讲完流程和排查说几句实在话。性能测试入门不难难的是养成“先想清楚再动手”的习惯。我见过不少人一上来就开压测工具疯狂加并发等到系统崩了再去翻日志这其实是在用蛮力替代思考。我的切身体会是性能测试最值钱的部分永远在测试设计和结果分析这两头。压力工具只是中间的执行环节不是核心竞争力。同样的系统有人压完只能说出“扛不住”三个字有人能圈出瓶颈位置、给出调优方向、算出容量水位差距不在工具多熟而在对系统运行机制的理解有多深。最后再分享一个实用技巧每一次压测前给环境拍个快照把代码版本、配置参数、数据量、压测模型、监控指标都记下来。很多人压测结果对不上回过头来根本不知道上一次用的是哪个版本的代码是哪些参数。把环境信息固定住你的每一次压测才有可比性性能优化这条路才能越走越清晰。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →