基本原理
压测的主要目的是对目标服务的特定指标进行压力测试,衡量服务的服务能力,根据压测的结果,对服务的承受能力进行预估。
服务能力相关的指标:
- 吞吐量(QPS)
- 响应时间
其他指标:
- 内存
为了得到上述指标,需要对目标服务进行大量的请求得到统计数据。不同指标的测试方法略有不同
- 吞吐量 = 可服务的最大请求数量/时间
- 响应时间 = 请求返回时间 - 请求到达时间
- 内存 = 在特定吞吐量下的内存申请的最大值
注:可服务是指系统还可以继续处理新的请求,一般而言就是CPU的使用率达到某个阈值就认为达到极限了,比如80%.
服务性能指标
CPU Load
CPU Load = 某一个时间点,正在使用CPU的进程数量 + 等待CPU的进程数量
更直接点说,CPU Load = 可运行的进程数。用来衡量机器负载是,CPU Load通常需要与CPU Core求比值。
衡量CPU Load指标时需要参考CPU的数量,在单核机器上,如果CPU Load > 1,意味着有进程需要等到CPU;在4核机器上,如果CPU Load=2,表明平均只有两个CPU得到使用。
一般认为:CPU Load/CPU 数量 在0.7~1之间是比较合理的。
Linux会将IO阻塞的进程也算入等待CPU的进程中,因此如果CPU Load非常高,也可以尝试确认是否是因为IO造成的。
CPU Usage
CPU Usage = 在一段时间内,CPU处理指令的时间 / (CPU处理指令的时间 + CPU进行IO等待的时间 + CPU IDLE的时间)
https://gist.github.com/haridsv/0d65d263b7f5f79a73e5
压测平台
压测的原理是模拟大批量客户端请求服务器,记录服务的响应时间,内存等指标。
流程:
CPU,内存
记录响应时间 IO,网络 (mock)
发压服务 --------------> 目标服务 -------------> 下游服务
| |
| - --- -- - - -- -------------
| (key有stress前缀) | (读写影子表)
- - - - > Redis - -> MySQL
存储层改造
压测需要在线上进行,由于请求非常多,容易造成脏数据。为了避免脏数据,服务端需要对压测数据进行标记或隔离,以便不影响正常的数据。
-
MySQL
目前采取的方案是为压测流量单独建立一个影子表,所有压测数据的操作都使用这个影子表。 -
Redis
- 对于压测流量,在写Redis时,都在Redis key 加上前缀,来与正常流量key以区分,避免造成数据污染
- 对于stress_tag:xxx(xxx表示压测标记值) 的压测流量,读写Redis时,实际会使用 xxx_key来进行操作
Redis中的压测数据需要人工删除,通过获取xxxx 为前缀的key,进行统一删除(与Redis同学沟通过,目前还是可以通过scan的方式扫描全部)
压测流程
- 首先要明确压测的目标
- 服务现状:接口当前QPS,Pct99,CPU,Memory等
- 预期性能目标:QPS,Pct99,CPU,Memory,Error_Rate等
- 一般情况QPS=峰值QPS*1.5,
- cpu和memory的压测目标,一般都设置在70%的利用率,不建议设置太高
- 然后梳理服务的链路:
- 可以手动进行梳理
- 也可以通过压测平台提供的链路梳理(logid关联)
-
明确风险点
如果下游服务不能参与压测,要进行mock,mock可通过平台配置:https://site.bytedance.net/docs/300/467/33117/ -
制定压测计划
-
起始QPS,结束QPS,持续时间,QPS步长等
-
压测过程中,要关注服务的告警,错误日志等信息
压测模式
1.单条数据重复查询
提前将随机生成的多条数据插入到数据库中,重复查询某一条数据
作用:测试下接口的QPS,响应时间;对于有缓存的场景,测试的结果表明最短响应时间
2.N条数据随机重复查询
提前将随机生成的多条数据插入到数据库中,每次请求随机待查询数据的ID
作用:测试接口的QPS,响应时间;对于没有缓存的场景,与1作用相同;对于有缓存的场景,测试的结果表明多个用户场景下的响应时间
BOE验证
压测对BOE环境来说,流程基本上是类似的,但唯一的问题是,压测平台不支持流量打到BOE环境。所以没有办法在BOE环境使用压测平台。
压测平台之所以不支持BOE,唯一的原因是因为在BOE环境没有对应的发压服务。所以,如果希望在BOE环境验证压测逻辑,可以手动构造压测请求,下面具体介绍下。