1、压测前要清楚的事
1.1 明确压测类型
要明确压测类型,这决定了压测使用的环境、压测策略,及输出的测试报告。类型可能有:
- 调优
- 容量摸底,对线上容量(系统、链路、对象)进行摸底
-
1.2 明确压测对象
压测之前要弄清楚,自己测什么
单接口
- 单个应用
- 单链路
- 全链路
1.3 指定合理的停止条件
条件一:最大 cpu 使用量目前我们线上配置的告警阀值一般是连续两次大于70%,或者一分钟累计5次大于70%
条件二:响应时间
一般参考 90% 的响应时间不大于某个值,具体的选择可以参考:
- 上游系统的客户端超时时间
- 服务中心配置的针对不同域的最大响应时间
条件三:网络流量使用
目前线上配置的告警阀值物理机流量使用大于网卡带宽80%,容器流量大于400Mbps
条件四:错误日志
5xx、4xx、包括业务超时、框架出错、如线程池爆了
条件五:gc 情况
ygc:看 fgc 的时间占比,理论上 gc 时间占比超过 10%,可以作为调优的一个备选项
fgc:要从多个维度看:
- 看 fgc 时间的占比,理论上 gc 时间占比超过10%,可以作为调优的一个备选项;
- 结合具体的业务诉求,假如1个小时1次,而且每次 gc 时间都要花 500ms 以上,或者已经很明显的导致业务出现响应超时,这个时候也要优化,当然1个小时6次肯定也要考虑排查和优化
oom:当业务 oom 的时候,也要考虑排查和优化了
1.4 性能风险评估
1.4.1 代码层面
- SQL 语句的数量及性能
- 外部接口调用的数量及超时配置
- 批量接口,不同入参 size 大小的区别
- 该缓存的东西是否有缓存
- 对于同样一份信息。有没有重复去查一个外部接口和重复查 db 或者缓存
- 锁:不该用锁的地方是有用了锁;该用锁的地方是否忘了锁
- 循环:循环嵌套的合理性、会不会出现死循环
日志:日志频率的合理性、日志序列化位置的合理性、Log4j 的配置
Log4j 的配置
输出到 console 是输出到本地磁盘(无缓存)的1.33倍
- 无缓存输出到本地磁盘是加缓存输出到本地磁盘的1.09倍(实际情况 buffersize 不一样,性能也不一样)
- 输出到本地磁盘(无缓存)+输出到 console 是输出到本地磁盘(无缓存)的1.48倍
-
1.4.2 系统组件配置层面
JVM
各种垃圾回收器的选择
- -XXPermSize、-XX:MaxPermSIze
-Xmn、-XX:NewRatio、-XX:SurvivorRatio = 64
redis
是否启动账户校验
- 集群的实例数量
- 单 key 的大小,单 key 超过 Ethernet MTU 是会明显下降
- 是否部署到虚拟机,官网说部署在虚拟机会比较慢
- 使用长连接还是短连接
- 服务端、客户端连接数量配置
- 数据结构的选择,比如我们 DBA 优先推荐使用 hash 接口,体积小,省内存
-
kafka
request.required.acks = -1(all) | 0 | 1, producer.type = sync/asyn
- min.insync.repilcas
- 每个 topic patition 数量的大小
-
MC
单实例的最大内存配置
- 实例的个数
- 是否禁用 CAS 命令(可以禁止版本计数,减少开销)
- 单 key 的存储内容大小
- 服务端和客户端的最大同时连接数
-
MySQL
log-bin 的开关
- sync_binlog,并发量高的情况下可损失5倍的性能
- performance_schema 功能的开关情况,会降低10~20个百分点的性能
- AHI (子适应索引),并不是开启了一定能加速查询,有可能会弊大于利,因为并发有可能会导致锁竞争(5.5只有1把全局锁,5.7有17把全局锁),尤其对于多表 join、模糊查询和查询条件经常变的场景
- DB 的数量,当 DB 是瓶颈时,一个库和两个库结果肯定是不一样的
- DB 的索引:是否能命中索引,走的索引是否最优
- DB 中数据量,100条数据和1000万条数据的查询响应时间肯定不一样
- DB 中的数据类型分布:如 pos 这边所有尺码都是单仓的和所有尺码都是多仓的肯定不一样
- DB 的最大连接数:max_conncetions;back_log:tcp 链接请求等待栈,并发量大是适当调大这个值,增加短时间内处理链接的数量
- DB 的链接线程池大小
- 是否开启 query cache:要权衡利弊,只适用于表数据不经常修改的场景,如果表数据频繁修改或者查询条件经常变,一方面命中率低,另一方面是频繁删除缓存,会给系统带来二次的开销
- thread_cache_size:通过查询 show global status like “Thread%”;查看 thread_created 的值,如果太大说明 mysql 一直在创建线程,可以适当调整一下这个值
- 配置中心
IBP(innodb buffer pool) 配置:
- innodb_buffer_pool_size 越大,可以减少回磁盘查询的概率,但太大就会产生 swap 页交换,推荐 IBP 大小设置为80%的系统物理内存
- innodb_buffer_pool_instances,建议设置为 innodb_read_io_threads + innodb_write_io_threads 之和
- innodb_read_io_threads 和 innodb_write_io_threads ,根据查询出来的读写比例配置
- innodb_log_file_size,redo log 的日志大小,理论上越大,那触发检查点的概率越小,对性能损耗越小,但太大则恢复时间长,不方便管理,建议 1G
- innodb_flush_log_at_trx_commit:控制 redo log 的落盘策略,1是实时洛到磁盘,2是实时洛到文件,然后再洛磁盘,0是1s刷新到文件和磁盘
堆内外缓存
最大存储对象的维度:内存使用维度还是存储数量维度
- 最大存储配置
-
系统拓扑
操作系统
1.4.3 硬件配置
CPU 的型号,核数量,主频
- 网络带宽
- 内存,java 应用如果不用堆内外缓存,只要内存能够满足 java 堆的配置即可,但如果用到堆内外缓存,这个时候,内存越大,可分配的缓存空间越大,在数据量大的场景下,性能可能更好
磁盘类型,比如固态硬盘和机械硬盘性能肯定不一样,同时机械硬盘,转速不一样性能也不一样
1.4.4 数据容量维度
分布式缓存 hotkey 概率
- 分布式缓存单 key 大小
- 分布式缓存是否能容纳全部的业务数据
- 本地缓存是否能全部容纳所有业务的数据
-
1.4.5 压测场景或者流量建模
多少用户场景
- 多少数据场景
-
1.4.6 监控方式及指标确定
压力机端监控
- 服务端的监控
- 给组件的监控
2、不同类型的测试策略
2.1 调优
- 环境:建议线下,而且只针对单系统或者接口,mock 外部依赖系统,但不要 mock 中间件,软件的参数配置优先用线上的
- 策略:摸底 —> 找到第一瓶颈 —> 调优对比
效果评估方法:服务端承受同样的 qps 压力下的资源占用对比
2.2 容量评估
2.2.1 环境
2.2.2 策略
读接口:日常流量放大比例回放;跟进场景人为构造不同参数流量去放大回放
- 读链路:日常流量放大比例回放;针对链路中压力不足的单个应用使用补流量的方式使得系统压力符合预期
- 写接口:通过调整集群中某台机器的权重,使其慢慢承担更多该接口的线上真实流量(读写混合),以便验证其单机能支持多少写 qps
- 写链路:无法生产执行
系统全链路容器评估
顺序:先单系统评估再全链路评估
单系统容量评估方式:
- 日常流量能触及单机上限情况:通过调权重的方式压测读写混合流量情况下单机容量*机器数量等到容量 A;通过读接口放大比例回放压测整个应用得到容量 B,取 A 和 B 最小值
日常流量无法触及单机上限的情况:只能把所有流量打到一台机器上,按比例折算出单机的容量 * 机器数量等到容量 A,通过读接口方式比例回放压测整个应用得到容器 B,取 A 和 B 最小值
2.3 稳定性
环境:建议线下
策略:选择负载最大的链路临界负载 + 脉冲交替持续跑1天后观察各项指标,尤其内存3、压测报告
背景
目的
环境部署拓扑
参数 & 配置软件参数,包括 jvm 和各组件
- 硬件配置(所有,包括压力机)
各场景过程数据
问题及现状(已优化或者无法优化、待优化等)
结论:调优的要说明是否有效果;容量和稳定性的要强调是否达标
注:重点强调,报告中不要有分析过程,只需要过程数据结果及结论
