性能压测,是系统上线前必不可少的环节,通过压测,能了解系统的性能瓶颈,评估系统的承载能力,发现系统的问题,优化系统的性能,保证系统上线后,能稳定运行,支撑预期的用户量和并发量。
JMeter,是Apache开源的压测工具,功能强大,支持多种协议(HTTP、HTTPS、FTP、JDBC、JMS、SOAP、TCP等),可扩展性好,插件丰富,是最常用的开源压测工具。但是,单机JMeter的压测能力有限,受限于CPU、内存、网络、端口等,一般单机能支撑几千到几万的并发,要支撑更高的并发,比如几十万、上百万的并发,就需要分布式架构设计,把压测任务分发到多台压测机,并行执行,汇总结果。
我们团队,做过很多次高并发的性能压测,从几千并发,到几十万并发,踩过很多坑,也总结了一些JMeter分布式压测的架构设计经验。今天就来分享一下,JMeter高可用高并发压测的架构设计和最佳实践,希望能给大家一些参考。
一、性能压测的基本概念
在讲架构设计之前,先简单介绍一下性能压测的基本概念,方便大家理解。
1. 什么是性能压测: 性能压测,是通过模拟大量用户,并发访问系统,测试系统的性能指标,比如响应时间、吞吐量、并发数、错误率、资源使用率等,评估系统的承载能力,发现性能瓶颈,优化系统性能的过程。
2. 性能压测的类型:
- 负载测试(Load Testing): 模拟预期的用户负载,测试系统在正常负载下的性能,看是否能满足性能要求。
- 压力测试(Stress Testing): 模拟超过预期的用户负载,甚至极限负载,测试系统在高负载下的性能,看系统的极限在哪里,会不会崩溃,崩溃后能不能恢复。
- 并发测试(Concurrency Testing): 模拟大量用户同时访问同一个功能,测试系统的并发处理能力,看有没有并发问题,比如死锁、竞态条件、数据不一致等。
- 稳定性测试(Endurance Testing/Soak Testing): 模拟一定的负载,长时间运行,测试系统的稳定性,看有没有内存泄漏、资源泄漏、性能下降等问题。
- 峰值测试(Spike Testing): 模拟用户量突然激增,测试系统在突发流量下的性能,看能不能扛住峰值流量。
- 容量测试(Volume Testing): 模拟大量的数据,测试系统在大数据量下的性能,看数据库、存储等能不能扛住。
3. 性能压测的核心指标:
- 响应时间(Response Time): 从请求发出,到响应收到的时间,包括网络传输时间和服务器处理时间,是用户最直观的感受。
- 吞吐量(Throughput): 单位时间内,系统处理的请求数,比如每秒请求数(QPS/TPS),反映系统的处理能力。
- 并发数(Concurrency): 同时访问系统的用户数,或者同时处理的请求数,反映系统的并发承载能力。
- 错误率(Error Rate): 失败的请求数占总请求数的比例,反映系统的稳定性。
- 资源使用率(Resource Utilization): 服务器的CPU、内存、磁盘IO、网络IO等资源的使用率,反映系统的资源瓶颈。
4. 性能压测的流程:
- 需求分析: 明确压测的目标、范围、场景、指标、通过标准。
- 场景设计: 设计压测场景,包括用户行为、并发数、持续时间、递增方式等。
- 脚本开发: 用JMeter开发压测脚本,模拟用户行为,参数化,关联,断言等。
- 环境准备: 准备压测环境,包括压测机、被测系统、测试数据、监控工具等。
- 预压测: 小规模压测,验证脚本的正确性,环境的可用性,调优脚本和环境。
- 正式压测: 按照压测计划,执行正式压测,收集性能指标,监控系统资源。
- 结果分析: 分析压测结果,定位性能瓶颈,找出问题。
- 优化调优: 根据分析结果,优化系统,调优参数,然后再压测,直到满足性能要求。
- 报告编写: 编写压测报告,总结压测结果,性能指标,问题和优化建议。
二、JMeter的基本使用
JMeter,是Apache开源的压测工具,基于Java开发,跨平台,功能强大,支持多种协议,可扩展性好。
JMeter的核心组件:
- 测试计划(Test Plan): JMeter测试的根节点,包含所有的测试元素。
- 线程组(Thread Group): 模拟用户组,每个线程代表一个用户,设置线程数(并发数)、 Ramp-Up时间(递增时间)、循环次数、持续时间等。
- 取样器(Sampler): 模拟用户的请求,比如HTTP请求、FTP请求、JDBC请求等,是压测的核心。
- 逻辑控制器(Logic Controller): 控制请求的执行逻辑,比如循环控制器、条件控制器、随机控制器、事务控制器等,模拟复杂的用户行为。
- 配置元件(Config Element): 配置请求的默认值,比如HTTP请求默认值、用户定义的变量、CSV数据文件设置、HTTP Cookie管理器、HTTP授权管理器等。
- 前置处理器(Pre-Processor): 在请求执行前,做一些处理,比如用户参数、JSR223预处理等。
- 后置处理器(Post-Processor): 在请求执行后,做一些处理,比如正则表达式提取器、JSON提取器、XPath提取器等,用于关联,从上一个请求的响应中提取数据,作为下一个请求的参数。
- 断言(Assertions): 验证请求的响应是否正确,比如响应断言、JSON断言、持续时间断言等,保证压测的请求是成功的,不是错误的。
- 监听器(Listener): 收集和展示压测结果,比如查看结果树、聚合报告、汇总报告、图形结果、响应时间图等,用于分析压测结果。
JMeter的基本使用流程:
- 新建测试计划。
- 添加线程组,设置并发数、递增时间、持续时间等。
- 添加配置元件,比如HTTP请求默认值、Cookie管理器、CSV数据文件等。
- 添加取样器,比如HTTP请求,配置请求的URL、方法、参数等。
- 添加后置处理器,比如JSON提取器,提取关联数据。
- 添加断言,验证响应的正确性。
- 添加监听器,查看压测结果。
- 保存测试计划,运行压测。
三、分布式压测的架构设计
单机JMeter的压测能力有限,要支撑高并发,需要分布式压测,把压测任务分发到多台压测机,并行执行,汇总结果。
1. Master-Slave架构
JMeter的分布式压测,采用Master-Slave架构,也就是一个主控节点(Master),多个工作节点(Slave/Worker)。
- Master节点: 负责管理压测任务,分发压测脚本到Slave节点,控制压测的启动、停止,收集Slave节点的压测结果,汇总展示。Master节点本身不发压测请求,只做管理和汇总。
- Slave节点: 负责执行压测脚本,发送压测请求,收集压测结果,把结果发送给Master节点。Slave节点是真正发请求的节点,每个Slave节点,都能支撑一定的并发数,多个Slave节点并行,就能支撑更高的并发。
架构图:
+-----------+ +-----------+ +-----------+
| Slave 1 | | Slave 2 | | Slave N |
+-----------+ +-----------+ +-----------+
^ ^ ^
| | |
+------------------+------------------+
|
+-----------+
| Master |
+-----------+
|
v
+-----------+
| 被测系统 |
+-----------+2. 压测机的规划
压测机的数量和配置,要根据预期的并发数来规划,首先要评估单台压测机能支撑多少并发,然后计算需要多少台压测机。
单台压测机的并发能力评估: 单台压测机的并发能力,受限于CPU、内存、网络、端口、JMeter的配置等,一般来说:
- 对于简单的HTTP请求,响应时间短,单台4核8G的压测机,大概能支撑5000-10000的并发。
- 对于复杂的请求,响应时间长,或者有大量的关联、断言、脚本处理,单台压测机的并发能力会低一些,可能2000-5000。
- 如果是HTTPS请求,因为加密解密的开销,并发能力会更低一些。
具体的并发能力,要通过预压测来评估,逐步增加单台压测机的并发数,看压测机的CPU、内存、网络是否达到瓶颈,压测结果是否准确,找到单台压测机的最大并发数。
压测机数量的计算: 总并发数 / 单台压测机的最大并发数 = 需要的Slave节点数,再加上1台Master节点,就是总的压测机数量。
比如,预期总并发数是10万,单台压测机最大支撑1万并发,就需要10台Slave节点,加上1台Master节点,总共11台压测机。
为了保险,建议多规划1-2台Slave节点,作为冗余,避免某台压测机出问题,影响总并发数。
压测机的配置要求:
- CPU: 压测是CPU密集型的,特别是HTTPS请求、脚本处理、结果收集,都很耗CPU,建议至少4核,高并发的话,8核、16核更好。
- 内存: JMeter是Java应用,需要堆内存,建议至少8G,高并发的话,16G、32G更好,JVM堆内存设置为物理内存的一半左右。
- 网络: 压测会产生大量的网络流量,要保证压测机的网络带宽足够,建议至少千兆网卡,高并发的话,万兆网卡更好,而且,压测机和被测系统,要在同一个内网,或者网络延迟很低,避免网络成为瓶颈。
- 操作系统: 建议用Linux,比Windows更稳定,性能更好,而且要优化操作系统的参数,比如文件描述符、端口范围、TCP参数等。
- Java版本: JMeter是Java应用,要安装合适的Java版本,建议用Java 8或者Java 11,64位,性能更好。
3. 任务分发
Master节点,负责把压测脚本分发到所有的Slave节点,控制压测的启动和停止。
任务分发的流程:
- 在Master节点上,编写压测脚本,保存为.jmx文件。
- 配置Master节点,指定所有Slave节点的IP和端口。
- 启动所有Slave节点的JMeter Server,等待Master的指令。
- 在Master节点上,启动压测,Master会把脚本分发到所有Slave节点。
- 所有Slave节点,同时执行压测脚本,发送请求。
- Master节点,可以随时停止压测,所有Slave节点会同时停止。
配置方法: 在Master节点的jmeter.properties文件里,配置remote_hosts,指定所有Slave节点的IP和端口,比如:
remote_hosts=192.168.1.101:1099,192.168.1.102:1099,192.168.1.103:1099然后,在每个Slave节点上,启动jmeter-server,默认端口是1099。
启动压测的时候,用命令行:
jmeter -n -t test.jmx -r-r表示远程启动所有Slave节点,也可以用-R指定特定的Slave节点:
jmeter -n -t test.jmx -R 192.168.1.101,192.168.1.102注意事项:
- Master和Slave节点,要用相同版本的JMeter和Java,避免版本不兼容。
- 脚本里的文件路径,比如CSV数据文件,要在所有Slave节点上都存在,路径一致,或者用相对路径,把文件和脚本一起分发。
- 脚本里的变量,要注意,每个Slave节点,都会独立执行脚本,变量是独立的,不会共享,如果需要全局唯一的变量,要注意设计。
- Master和Slave之间的通信,要保证网络通畅,端口开放,默认用的是RMI协议,端口1099,还有一些随机端口,建议关闭防火墙,或者配置固定端口。
4. 结果汇总
Slave节点,执行压测的时候,会把压测结果,发送给Master节点,Master节点汇总所有Slave的结果,展示总的压测指标。
结果汇总的方式:
- 实时汇总: 默认情况下,Slave节点会实时把结果发送给Master,Master实时汇总展示,这样,压测过程中,就能看到实时的压测指标。但是,高并发的时候,实时发送结果,会产生大量的网络流量,Master节点处理结果也会有压力,可能影响压测的准确性。
- 批量汇总: 可以配置Slave节点,批量发送结果,或者压测结束后,再发送结果,减少网络流量和Master的压力,提高压测的准确性。
结果汇总的优化:
- 高并发的时候,建议关闭不必要的监听器,比如查看结果树、图形结果等,这些监听器很耗资源,只保留聚合报告、汇总报告等必要的监听器。
- 可以配置JMeter,只保存汇总结果,不保存每个请求的详细结果,减少数据量。
- 可以把结果保存到文件,压测结束后,再分析,不要实时展示,减少Master的压力。
- 用命令行模式运行压测,不要用GUI模式,GUI模式很耗资源,影响压测性能,正式压测一定要用命令行模式。
5. 高可用设计
分布式压测,也要考虑高可用,避免某个节点故障,影响整个压测。
Master节点的高可用: Master节点是单点,如果Master节点挂了,整个压测就失控了,所以,要保证Master节点的稳定:
- Master节点,配置要足够,CPU、内存、网络,不要让Master成为瓶颈。
- Master节点,只做管理和汇总,不要同时做Slave,不要发请求,避免压力太大。
- 可以准备备用Master节点,如果主Master挂了,切换到备用Master,重新启动压测。
- 压测过程中,定期保存结果,避免Master挂了,结果丢失。
Slave节点的高可用: Slave节点,如果有一台挂了,会影响总并发数,所以,要保证Slave节点的稳定:
- 多规划1-2台Slave节点,作为冗余,即使有一台挂了,总并发数也能满足要求。
- Slave节点,配置要足够,不要让单台Slave的压力太大,CPU、内存、网络,不要超过80%。
- 压测过程中,监控Slave节点的状态,如果有Slave节点异常,及时处理,或者剔除。
- 所有Slave节点,配置一致,环境一致,避免因为环境差异,导致压测结果不准确。
网络的高可用: 网络是分布式压测的关键,网络不稳定,会影响压测的准确性,甚至导致压测失败:
- 压测机和被测系统,要在同一个内网,或者用专线,保证网络稳定,延迟低。
- 网络带宽要足够,压测前,评估压测产生的网络流量,保证带宽不会成为瓶颈。
- 可以用双网卡、链路聚合等,提高网络的可用性和带宽。
- 压测过程中,监控网络的使用率、延迟、丢包率,如果网络异常,及时处理。
四、高并发压测的优化
要支撑高并发的压测,需要从多个方面优化,包括压测机优化、JMeter优化、网络优化、被测系统优化等。
1. 压测机优化
操作系统优化(Linux):
- 文件描述符: 压测会打开大量的文件描述符(网络连接也是文件描述符),默认的文件描述符限制是1024,远远不够,要调大,比如65535,甚至更大。
修改/etc/security/limits.conf: `` soft nofile 65535 hard nofile 65535 ``
- 端口范围: 压测会用大量的本地端口,默认的端口范围可能不够,要调大。
修改/etc/sysctl.conf: `` net.ipv4.iplocalport_range = 1024 65535 ``
- TCP参数: 优化TCP参数,提高网络性能,比如:
`` net.ipv4.tcptwreuse = 1 net.ipv4.tcptwrecycle = 1 net.ipv4.tcpfintimeout = 30 net.core.somaxconn = 65535 net.core.netdevmaxbacklog = 65535 net.ipv4.tcpmaxsyn_backlog = 65535 ``
- 关闭防火墙: 压测机的防火墙,可能会影响网络性能,建议关闭,或者配置好规则。
- 关闭不必要的服务: 关闭压测机上不必要的服务,释放CPU和内存资源。
JVM优化: JMeter是Java应用,JVM的参数,对性能影响很大:
- 堆内存: 堆内存要设置足够,避免频繁GC,或者OOM,建议设置为物理内存的一半左右,比如物理内存16G,堆内存设置8G:
`` HEAP="-Xms8g -Xmx8g" ``
- GC算法: 用G1垃圾回收器,性能更好,停顿更短:
`` GC_ALGO="-XX:+UseG1GC -XX:MaxGCPauseMillis=200" ``
- 元空间: 元空间设置足够,避免元空间溢出:
`` -XX:MaxMetaspaceSize=512m ``
2. JMeter优化
脚本优化:
- 减少不必要的组件: 脚本里,不要加不必要的组件,比如不必要的监听器、断言、后置处理器等,每个组件都会消耗资源,影响性能。
- 优化关联和断言: 关联和断言,很耗CPU,特别是正则表达式、JSON解析,要优化,尽量用简单的表达式,避免复杂的正则,能不用的就不用。
- 参数化优化: 用CSV数据文件做参数化,比用用户参数、随机函数性能更好,CSV文件要放在所有Slave节点上,路径一致。
- 避免在脚本里做复杂的计算: 尽量不要在JMeter脚本里做复杂的计算、逻辑处理,这些很耗CPU,如果需要,尽量在被测系统里做,或者用JSR223+Groovy,比BeanShell性能好很多。
JMeter属性优化:
- 关闭GUI: 正式压测,一定要用命令行模式,不要用GUI模式,GUI模式很耗资源,影响压测性能。
- 调整批量发送结果的参数: 高并发的时候,调整结果发送的批量大小,减少网络流量,比如:
`` mode=StrippedBatch ``
- 调整HTTPClient的参数: 用HttpClient4,比默认的HttpClient性能更好,连接池设置足够:
`` httpsampler.httpsampler4=true httpclient4.maxconnections=0 httpclient4.maxconnectionsperhost=0 ``
- 关闭Cookie管理器的自动保存: 如果不需要Cookie,就不要加Cookie管理器,或者关闭自动保存,减少资源消耗。
监听器优化:
- 高并发的时候,只保留必要的监听器,比如聚合报告、汇总报告,关闭查看结果树、图形结果、响应时间图等,这些很耗资源。
- 不要在压测过程中,实时查看结果树,会严重影响性能,结果树只在调试脚本的时候用。
- 把结果保存到JTL文件,压测结束后,再用GUI打开分析,不要实时展示。
3. 网络优化
- 内网压测: 压测机和被测系统,尽量在同一个内网,避免公网的延迟、丢包、带宽限制,影响压测的准确性。
- 带宽评估: 压测前,评估压测产生的网络流量,比如每个请求的平均大小,乘以QPS,就是需要的带宽,保证压测机和被测系统的网络带宽都足够,不会成为瓶颈。
- 减少请求大小: 压测脚本里,请求的参数、Body,尽量小,不要传不必要的大参数,减少网络流量。
- 启用压缩: 如果被测系统支持Gzip压缩,可以在请求头里加Accept-Encoding: gzip,减少响应的大小,降低网络流量,但是要注意,解压会耗CPU。
- 网络监控: 压测过程中,监控网络的使用率、延迟、丢包率,如果网络成为瓶颈,要增加带宽,或者优化请求。
4. 被测系统优化
压测的目的,是测试被测系统的性能,所以,被测系统本身也要优化,才能测出真实的性能,不然,被测系统有问题,压测结果也不准确。
- 应用服务器优化: 比如Tomcat、Nginx,优化连接数、线程数、超时时间、Gzip压缩等。
- 数据库优化: 优化索引、SQL语句、连接池、缓存,分库分表等,避免数据库成为瓶颈。
- 缓存优化: 用Redis等缓存,减少数据库的查询,提高响应速度。
- 代码优化: 优化业务代码,减少不必要的计算、数据库查询、网络调用,提高代码的执行效率。
- 资源监控: 压测过程中,监控被测系统的CPU、内存、磁盘IO、网络IO、JVM、数据库等,找到性能瓶颈。
五、压测场景设计
压测场景的设计,很重要,不同的场景,测出来的结果不一样,要根据业务的实际情况,设计合理的压测场景。
1. 基准场景: 模拟正常的用户负载,也就是系统上线后,预期的日常用户量和并发量,测试系统在正常负载下的性能,看是否满足性能要求,这是最基本的场景。
2. 峰值场景: 模拟系统的峰值流量,比如大促、活动、秒杀的时候,用户量突然激增,测试系统在峰值流量下的性能,看能不能扛住峰值,会不会崩溃,崩溃后能不能恢复。
3. 递增场景: 并发数从低到高,逐步增加,比如从100并发,每分钟增加100,直到10000并发,测试系统在不同并发下的性能,找到系统的拐点,也就是性能开始急剧下降的那个并发数,就是系统的最大承载能力。
4. 稳定性场景: 模拟一定的负载,长时间运行,比如24小时,甚至72小时,测试系统的稳定性,看有没有内存泄漏、资源泄漏、性能下降、错误率升高等问题。
5. 混合场景: 模拟真实的用户行为,不同的用户,做不同的操作,比如浏览商品、搜索、下单、支付、查看订单等,按照一定的比例混合,更贴近真实的业务场景,测出来的结果更准确。
6. 异常场景: 模拟异常情况,比如某个服务挂了,数据库慢查询,网络延迟,丢包等,测试系统在异常情况下的表现,看有没有降级、熔断、限流,能不能保证核心功能可用。
场景设计的注意事项:
- 要贴近真实的业务场景,不要凭空设计,根据业务的实际用户行为、流量模型来设计。
- 要考虑用户的思考时间,真实用户,操作之间会有间隔,不是不停地发请求,要在脚本里加合理的思考时间(定时器)。
- 要参数化,用户数据、请求参数,要参数化,不要所有用户都用同一个数据,不然可能命中缓存,测出来的结果不准确,也可能有并发问题。
- 要有关联,比如登录后,提取Token,作为后续请求的参数,模拟真实的用户会话。
- 要有断言,验证请求的响应是否正确,保证压测的请求是成功的,不是错误的,不然,错误的请求,响应时间很短,测出来的QPS很高,但是没有意义。
六、压测指标分析
压测结束后,要分析压测结果,找到性能瓶颈,给出优化建议。
核心指标分析:
- 响应时间:
- 平均响应时间:所有请求的平均响应时间,反映系统的整体性能。 - P50/P90/P95/P99响应时间:不同百分位的响应时间,反映响应时间的分布,P99很重要,因为大部分用户的体验,取决于慢的那部分请求。 - 最大响应时间:最慢的请求的响应时间,反映系统的最坏情况。 - 响应时间的变化趋势:随着并发数的增加,响应时间的变化,找到响应时间急剧上升的拐点。
- 吞吐量(QPS/TPS):
- 平均QPS:每秒处理的请求数,反映系统的处理能力。 - 最大QPS:峰值的QPS,反映系统的最大处理能力。 - QPS的变化趋势:随着并发数的增加,QPS的变化,找到QPS的峰值,也就是系统的最大吞吐量,超过这个并发数,QPS不会再增加,甚至会下降。
- 并发数:
- 系统能支撑的最大并发数,也就是在满足响应时间和错误率要求的前提下,最大的并发用户数。
- 错误率:
- 错误的请求数占总请求数的比例,正常情况下,错误率应该为0,或者很低,比如低于0.01%。 - 错误的类型,是连接超时、读取超时、500错误、404错误,还是断言失败,分析错误的原因。
- 资源使用率:
- CPU使用率:服务器的CPU使用率,如果CPU达到100%,说明CPU是瓶颈。 - 内存使用率:服务器的内存使用率,如果内存很高,或者有频繁的GC,说明内存是瓶颈,可能有内存泄漏。 - 磁盘IO:磁盘的IO使用率,如果磁盘IO很高,说明磁盘是瓶颈,可能是数据库的磁盘IO,或者日志写入。 - 网络IO:网络的使用率,如果网络带宽打满了,说明网络是瓶颈。 - 数据库指标:数据库的连接数、QPS、慢查询、锁等待等,分析数据库的瓶颈。
性能瓶颈定位: 根据压测指标,分析性能瓶颈在哪里:
- 如果CPU使用率很高,QPS上不去,响应时间很长,说明是CPU密集型的瓶颈,可能是代码计算太复杂,或者加密解密,或者GC太频繁。
- 如果CPU使用率不高,但是QPS上不去,响应时间很长,说明是IO密集型的瓶颈,可能是数据库查询慢,或者网络调用慢,或者磁盘IO慢。
- 如果数据库的CPU、IO很高,慢查询很多,说明数据库是瓶颈,需要优化SQL、索引,或者分库分表,或者加缓存。
- 如果网络带宽打满了,说明网络是瓶颈,需要增加带宽,或者优化请求大小,启用压缩。
- 如果错误率很高,是连接超时,说明系统的连接数不够,或者并发太高,系统处理不过来,连接队列满了。
- 如果错误率很高,是读取超时,说明系统处理太慢,响应时间超过了超时时间。
七、压测报告编写
压测结束后,要编写压测报告,总结压测结果,性能指标,问题和优化建议。
压测报告的内容,一般包括:
- 压测背景和目标: 为什么做这次压测,压测的目标是什么,要验证什么。
- 压测环境: 压测机的配置、数量,被测系统的架构、配置,网络环境,测试数据等。
- 压测场景: 压测的场景设计,并发数,持续时间,用户行为模型,递增方式等。
- 压测结果: 核心性能指标,包括响应时间、QPS、并发数、错误率、资源使用率等,用表格和图表展示。
- 结果分析: 分析压测结果,系统的性能是否满足要求,性能瓶颈在哪里,是什么原因导致的。
- 问题和优化建议: 压测中发现的问题,以及对应的优化建议,比如代码优化、数据库优化、缓存优化、配置优化等。
- 结论: 总结压测的结论,系统能不能上线,能不能支撑预期的并发量,还需要做哪些优化。
压测报告,要清晰、准确、有数据支撑,不要写空话,要有具体的指标,具体的问题,具体的优化建议,让开发和运维,能根据报告,定位问题,优化系统。
八、踩坑经验和最佳实践
最后,分享一些我们踩过的坑,和总结的最佳实践。
踩过的坑:
- 压测机性能不够,导致压测结果不准确: 一开始,我们用的压测机配置很低,单台只能支撑几千并发,要测10万并发,需要很多台,但是我们没那么多机器,就硬上,结果压测机的CPU、内存都打满了,压测结果不准确,QPS上不去,响应时间很长,我们以为是被测系统的问题,优化了很久,后来才发现是压测机的问题,换了高配的压测机,结果就好了。所以,压测前,一定要评估压测机的性能,保证压测机不会成为瓶颈。
- 网络带宽不够,导致压测结果不准确: 有一次,我们压测,QPS上不去,响应时间很长,错误率很高,查了很久,发现是网络带宽打满了,压测机和被测系统之间的网络,只有百兆,很快就打满了,后来换成千兆,问题就解决了。所以,压测前,一定要评估网络带宽,保证网络不会成为瓶颈。
- 脚本没有断言,压测的都是错误请求: 有一次,我们压测,QPS很高,响应时间很短,我们以为系统性能很好,后来一看,大部分请求都是404错误,因为脚本的URL写错了,但是我们没有加断言,所以都算成功了,白测了。所以,压测脚本一定要加断言,验证请求的响应是否正确,保证压测的请求是成功的。
- 参数化没做好,所有用户用同一个数据: 有一次,我们压测查询接口,所有用户都查同一个ID,结果都命中了缓存,QPS很高,我们以为系统性能很好,后来换了不同的ID,QPS一下子就下来了,因为缓存命中率低了,都查数据库了。所以,压测脚本一定要做好参数化,用户数据、请求参数,要随机,要不同,贴近真实的场景。
- GUI模式压测,性能很差: 一开始,我们用JMeter的GUI模式压测,结果GUI很卡,压测机的CPU很高,压测结果不准确,后来才知道,正式压测要用命令行模式,GUI模式只用来调试脚本和查看结果。所以,正式压测一定要用命令行模式,不要用GUI模式。
- Master节点压力太大,结果汇总不及时: 有一次,我们用了20台Slave,高并发,结果Master节点的CPU、内存都打满了,结果汇总不及时,压测结束后,等了很久才出结果,而且结果还有丢失。后来,我们优化了Master节点的配置,关闭了不必要的监听器,批量发送结果,问题就解决了。所以,Master节点的配置要足够,不要让Master成为瓶颈。
- Slave节点时间不同步,结果不准确: 有一次,我们的Slave节点,时间没有同步,有的快,有的慢,结果汇总的时候,响应时间、QPS都不准确,后来用NTP同步了所有节点的时间,问题就解决了。所以,所有压测机的时间,一定要用NTP同步,保证时间一致。
最佳实践:
- 压测前做预压测: 正式压测前,先做小规模的预压测,验证脚本的正确性,环境的可用性,调优脚本和环境,评估单台压测机的并发能力,没问题了,再做正式压测。
- 用命令行模式压测: 正式压测,一定要用命令行模式,不要用GUI模式,GUI模式只用来调试脚本和查看结果。
- 做好参数化和关联: 压测脚本,要做好参数化,用户数据、请求参数,要随机,要不同,做好关联,模拟真实的用户会话,贴近真实的业务场景。
- 加断言: 压测脚本一定要加断言,验证请求的响应是否正确,保证压测的请求是成功的,不是错误的。
- 监控所有节点: 压测过程中,要监控所有节点,包括压测机(Master和Slave)、被测系统的服务器、数据库、缓存等,监控CPU、内存、磁盘IO、网络IO等,及时发现瓶颈。
- 时间同步: 所有压测机和被测系统的时间,要用NTP同步,保证时间一致,结果准确。
- 逐步增加并发: 压测的时候,不要一下子就加到最高并发,要逐步增加,比如从1000开始,每次增加1000,稳定运行几分钟,再增加,这样,能看到不同并发下的性能,找到拐点,也避免一下子把系统打挂。
- 多次压测,取平均值: 压测会有波动,不要只压一次就下结论,要多次压测,取平均值,或者稳定的结果,这样更准确。
- 压测后清理环境: 压测结束后,要清理测试数据,恢复环境,避免影响后续的测试和正常的业务。
- 持续优化,反复压测: 性能优化是一个持续的过程,发现问题,优化,再压测,再优化,直到满足性能要求,不要指望一次优化就能解决所有问题。
写在最后
性能压测JMeter架构设计:高可用高并发。
性能压测,是系统上线前必不可少的环节,通过压测,能了解系统的性能瓶颈,评估系统的承载能力,发现系统的问题,优化系统的性能。JMeter是最常用的开源压测工具,功能强大,但是单机的压测能力有限,要支撑高并发,需要分布式架构设计,Master-Slave架构,多台压测机并行,汇总结果。
本文分享了性能压测的基本概念、JMeter的基本使用、分布式压测的架构设计(Master-Slave架构、压测机规划、任务分发、结果汇总、高可用设计)、高并发压测的优化(压测机优化、JMeter优化、网络优化、被测系统优化)、压测场景设计、压测指标分析、压测报告编写、踩坑经验和最佳实践,希望能给大家一些参考。
性能压测是一门技术活,不仅要会用工具,还要会设计场景,分析结果,定位瓶颈,优化系统,掌握JMeter的分布式架构设计,能支撑更高的并发,更准确地评估系统的性能。
最后,用一句话结尾:
"性能压测不是目的,发现问题、优化系统、保证系统稳定运行才是目的。用好JMeter,做好分布式压测,能帮我们更准确地评估系统性能,发现问题,优化系统,让系统上线后,稳定运行,支撑业务的发展。"
祝大家都能做好性能压测,系统稳定运行,线上零故障!
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录