作者:拂衣
为什么要做压测
随着无线设备的普及和 5G 的大力建设,越来越多的线上系统、小程序成为了人们生活中必不可少的工具。与此同时,年底各类大促活动接踵而至,对于这些电商软件而言,都会面对一个问题:系统能承受多少用户同时访问,面对突发的流量洪峰,能否保证系统无故障稳定运行?
为了回答这个问题,就需要在系统上线前做多轮压力测试,提前模拟出复杂的, 高仿真的线上流量来验证整体系统的高可用性, 这也是实施系统高可用方案的关键环节。另外,通过不同阶段的压测,也完成对系统的容量规划、瓶颈探测,对系统整体能力进行验收,确保在流量洪峰来临前,系统确实能够承受即将来临的真实线上压力。从某种意义上来说,压测是系统稳定性的验证者。
如何实施一次准确的性能压测
1. 准备压测环境
压测的执行环境是一个老生常谈的话题,如果直接在生产环境执行压测,会有 2 个问题:
- 会影响线上业务,对正常访问系统的用户造成影响2.会污染线上数据,将压测数据写入线上数据库为了解决这 2 个问题,一般业内采用如下几种方案:
以上方案各有优缺点,适用场景也不尽相同,可以根据自己项目所处的阶段灵活选择方案。
2. 构建压测脚本
业内常用的压测工具包括 JMeter、Gatling、Locust、k6、Tsung、阿里云 PTS 等。这些工具无一例外,都需要将压测业务的 API,编排为一个压测脚本。
这一步工作的重点在确认压测的 API,不要有遗漏,且 API 编排的顺序要符合用户的操作逻辑。对于电商业务的压测来说,如果脚本中遗漏了登录鉴权 API,那后面的订单、物流、库存等 API 都会在权限校验这步就报错,不会执行正常的业务逻辑,也就无法模拟真实的业务场景。
以上压测工具编排脚本都有 2 个方式:
- 手动输入脚本,这需要脚本的编写人员对业务非常熟悉,保证不会遗漏 API。
- 自动录制脚本,上述开源压测工具都提供了录制请求的代理功能,开启并配置代理后,只要在页面上模拟用户的操作和点击行为,即可自动录制请求,并生成压测脚本。同时 PTS 还提供了 Chrome 录制插件(链接1),免代理配置,可以一键生成 JMeter 和 PTS 压测脚本。提升了脚本编写的效率,也能保证不遗漏 API。
为了避免复杂脚本中遗漏 API 的风险,推荐使用录制功能生成脚本。
3. 确认压力模型
这一步是在配置压测中模拟的压力峰值、不同 API 的压力分布比例以及压力值递增模型。压力值指的是模拟并发用户数,或每秒发送的请求数。
- 施压模式
在设置之前,需要确认施压模式,业内主要有 2 种施压模式:
- 虚拟用户(VU)模式,可以理解为一个线程模拟一个真实用户,压测时线程一直循环执行,模拟用户不停地发送请求。
- 吞吐量模式,即每秒请求数(QPS),可以直接衡量服务端的吞吐量。在项目验收阶段,很重要的一个指标就是系统的吞吐量,即可支持的QPS。对于这种压测场景,更推荐使用吞吐量模式,可以直观的看到施压机每秒发出的请求数,并和服务端的吞吐量直接对应起来。
- 各 API 压力分布比例
确认了施压模式后,需要配置不同 API 的压力分布比例。每个 API 的准确压力分布比例,也是一次成功压测中不可获取的因素。
- 压力值递增模型
常见有脉冲模型,阶梯递增,均匀递增。脉冲模型会模拟流量在瞬间突然增大,常用于秒杀、抢购的业务场景。递增模型可以模拟在一定时间段内,用户量不断增大,常用于模拟有预热的业务场景。
除了常规的递增模型,最好在压测中可以实现手动调速功能,一是可以模拟一些非常规的流量递增情况,二是可以反复调整压力值,来复现和排查问题。
- 施压流量地域分布
确定了压力值和递增模型后,还需要确定施压流量的地域分布,应尽量拟合真实的用户分布,才能保证测试结果真实可信。对于区域性的在线业务,施压机分布在当地的同一机房,是可以理解的。如果是全国性的在线业务,施压机也应该按照用户分布,在全国各地域部署。
4. 执行压测,观察压测指标
压测中核心指标分为:请求成功率,请求响应时间(RT),系统吞吐量(QPS)
- 请求成功率不止要看全局的请求成功率,还要关注一些核心 API 的成功率,避免整体成功率达标,核心 API 成功率不足的情况。
- 请求响应时间,需要关注 99、95、90、80...等一些关键分位的指标是否符合预期,而平均响应时间没有太大的参考意义,因为压测需要保证绝大部分用户的体验,在不清楚离散程度的情况下,平均值容易造成误判。
- 系统吞吐量是衡量系统能承受多大访问量的指标,是压测不可缺少的标准。
上面三个指标遇到拐点时,就可以认为系统已经出现性能瓶颈,可以停止压测或调小压力值,准备分析、定位性能问题了。
除了这三个业务指标,同时还应该同时观测系统的应用监控、中间件监控和硬件监控的一些指标,包括但不限于:
服务器:
- 网络吞吐量
- CPU使用率
- 内存使用率
- 磁盘吞吐量
- ......
数据库:
- 连接数
- SQL 吞吐量
- 慢 SQL 数
- 索引命中率
- 锁等待时间
- 锁等待次数
- .....
中间件:
- JVM GC 次数
- JVM GC 耗时
- 堆内、堆外内存使用量
- Tomcat 线程池活跃线程数
- ......
更多压测时需要关注的指标,见文末文档 [ 2]
如果系统已经达到预期,往往还可以可以按照 10-20%的比例,不断加大压力值,为系统做一次峰值“摸高”,观察系统的极限值是多少,做到心里有底。
5. 复盘,性能优化
压测结束,如果未达到预期,可以配合监控排定位,分析性能问题,性能优化完成后,在下一轮压测中继续验证。
测试中问题分析和调优的方法这里不展开描述,可以参考文末文档 [ 3]
如果系统表现已经符合预期,可以用压测得到的系统吞吐量指标,配置流控、降级、系统或隔离规则,保障系统稳定性。
阿里云性能测试 PTS,助您系统无忧
性能测试 PTS(Performance Testing Service)是一款阿里云 SaaS 化的性能测试工具,从最早为了精准模拟双十一流量洪峰诞生,到现在已经走过了 10 个年头。每年支持包括双十一在内的全集团范围的几万次压测任务,是阿里内部双十一技术架构的"提前验证者"。
技术让利 1:自研 PTS 压测引擎,压力模型准,性能优
PTS 完全自研的压测引擎,在并发模型的实现上相较传统线程模型性能更优。并且支持 API 维度的吞吐量配置,比开源工具更精细,可以准确模拟流量漏斗模型。
PTS 压测还支持多种客户端的流量录制功能,可以快速构建压测脚本,并支持完全白屏化的操作,让压测脚本构建的门槛大大降低。
技术让利 2:全面兼容 JMeter,上线 JMeter 插件
PTS 在全面兼容 JMeter 的同时,针对 JMeter 分布式压测做了很多优化:
优化点 1:全球分布施压机,即压即用,可支持百万并发,千万 QPS 压测
优化点 2:支持吞吐量模式,可以设置全局目标 QPS,更直观衡量服务端性能
优化点 3:支持压测中调速,可以灵活调整并发或 QPS,不断逼近性能极限点
优化点 4:支持浏览器插件录制,一键导出 JMeter 脚本,无需配置代理,大大降低构建脚本的工作量
优化点 5:针对分布式压测,支持自动切分文件,支持全局生效 Timer、Controller 组件,零门槛开启分布式压测
优化点 6:发布 JMeter PTS 插件,使用 JMeter GUI 客户端即可发起云端分布式压测,无缝衔接脚本调试和执行阶段 [ 4]
技术让利 3:VPC 内网压测
在全面正式压测前,重点微服务应用需要在日常态做单应用的压测,摸清楚局部的性能极限。
对于部署在阿里云上的服务,单个微服务应用不会暴露公网入口,这时就需要压测工具有打通 VPC 内网的能力。
PTS 支持 VPC 内网压测,可以在压测时快速打通施压机与用户 VPC 网络,保证内网压测的网络畅通。在压测结束后,也会即时关闭网路通道,保证网络安全。
用户只需要在压测配置中,选择微服务应用所在的 VPC 内网、安全组、交换机,即可开启 VPC 内网压测。让您的服务无需暴露公网入口,也可以探测出性能指标。
操作示例如下:
技术让利 4:流量地域定制
大部分业务的用户并不是按地域均分的,相反,往往很不均匀。要模拟真实流量分布,施压机需要在各地分散部署,并且支持按地域、按量分配,在压测时,还要支持实时的统一调度。如果施压机都分布在一个 Region,甚至是一个可用区内,那是无法模拟出来自全球用户请求的。
使用阿里云性能测试服务(PTS)压测时,开启流量地域定制功能,只需简单勾选地域,即可指定施压机的地域分布,目前支持全球 22 个地域定制。
技术让利 5:问题诊断工具
压测的目的是发现性能问题,在压测报告中,PTS 有异常请求状态码的统计,并提供了请求采样日志,可以直观的看到请求、响应的全部信息,对于响应时间较长的请求,也会直观的展示请求在各个阶段的耗时。
对于 Java 应用,PTS 提供了基于 Java Agent 的问题诊断工具,只需在 Java 应用上挂载探针,即可自动获取应用、API、机器维度的秒级监控。对于报错的请求,可以直接定位到调用链上报错的方法堆栈,省去了大量排查问题的时间,是定位问题的“利器”。
定位报错方法堆栈示例如下:
相关链接
[1] Chrome录制插件使用指导:
https://help.aliyun.com/docum...
*[ 2] 压测指标:*
https://help.aliyun.com/docum...
*[3] 测试问题分析及调优:*
https://help.aliyun.com/docum...
*[4] JMeter插件使用指导:*
https://help.aliyun.com/docum...
*[5] PTS产品购买页:*
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。