记录性能测试的相关知识与实践:测试指标,测试工具,性能调优点
关于性能测试
性能测试是通过自动化的测试工具模拟多种正常
、峰值
以及异常
负载条件来对系统的各项性能指标进行测试。
负载测试和压力测试都属于性能测试,两者可以结合进行。
- 通过
负载测试
,确定在各种工作负载下系统的性能,目标是测试当负载逐渐增加
时,系统各项性能指标的变化情况。
压力测试
是通过确定一个系统的瓶颈
或者不能接受的性能点
,来获得系统能提供的最大服务级别
的测试。
测试指标
主要是从以下三个维度来衡量
- 响应时间:从用户角度
- Average (ms):服务平均响应时长
- Min (ms):服务最小响应时长
- Max(ms):服务最大响应时长
- 服务器资源:从系统角度
- 内存使用率:内存泄漏,内存溢出
- CPU负载
- 磁盘IO
- 网络IO
- 吞吐量:从业务角度
- Request:总请求数
- RPS(并发数/平均响应时间):服务每秒处理请求数
测试准备工作
工欲善其事必先利其器
服务器监控工具
prometheus
.node_exporter系统监控,或者zabbix
grafana
可视化监控指标
- 可用内存
- 可用磁盘
- CPU负载
- 网络流量
JVM监控工具
jps -lvm
查看java进程情况
Java VisualVM
在服务端启动jstatd
后,在本地用jdk自带的jvisualvm
连接:
测试框架
Locust
分布式性能测试框架
Locust的关键配置
压测Web界面配置
- Number of users to simulate:模拟的用户数,即压测的用户总数
- Hatch rate:压测时,每秒并发/启动的用户数
TaskSet脚本配置
- min_wait:模拟用户在执行任务之间等待的最小时间,单位是毫秒;
- max_wait:模拟用户在执行任务之间等待的最大时间,单位是毫秒;
默认1000,即locust在执行每个任务之间总是会等待1秒
测试环境搭建
服务器准备
- API服务器
- 缓存服务器
- 数据库服务器
- Web服务器
服务部署
Jenkins编写服务部署脚本
测试数据准备
小样本数据采用Junit单元测试调用API接口生成,
大样本数据用locust脚本生成
- 用户数据:100
- 人员数据:10000
- 设备数据:10000
- 设备人员关系数据:100000000
参数化
- 为尽量模拟压测的真实性,测试数据应从测试数据源中随机抽样生成;
locust测试脚本中可采用python的random从list中抽样;
或者用pandas的sample生成采样数据;
测试脚本
locust测试脚本示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
|
import pandas as pd import json import random import uuid
from locust import HttpLocust, TaskSet, task
class OpenPersonBackendApi(TaskSet): __PERSON_LIBS = None def person_query(self): """ 人员列表查询 :return: """ ysk_id, person_lib_id = self._get_person_lib() payload = { "ysk_id": ysk_id, "person_lib_id": person_lib_id, "limit": random.randint(10, 500) } headers = {'content-type': 'application/json'} r = self.client.post("/person_create", data=json.dumps(payload), headers=headers, verify=False) assert r.status_code == 200 rData = json.loads(r.text, encoding="utf-8") if rData["success"]: print("person_lib_id {},time {},person_id:{}".format(person_lib_id, time, rData["data"]["person_id"])) else: print(rData)
def _get_person_lib(self): if self.__PERSON_LIBS is None: self.__PERSON_LIBS = pd.read_csv("data/person_libs.txt").values.tolist() person_lib = random.choice(self.__PERSON_LIBS) ysk_id = person_lib[0] person_lib_id = person_lib[1] return ysk_id, person_lib_id
class OpenPersonLocust(HttpLocust): task_set = OpenPersonBackendApi host = "http://172.26.12.191:9881/open-person-backend/1.0" min_wait = 1000 max_wait = 1000
if __name__ == "__main__": """ master启动脚本:export node=master && python open_person_backend.py slave启动脚本:export node=salve && python open_person_backend.py """ import os
node = os.environ.get("node", "slave") if node == "master": os.system("nohup locust -f open_person_backend.py --master -P 9090 >>master.log &") else: os.system("nohup locust -f open_person_backend.py --slave --master-host=172.26.12.128 >>slave.log &") os.system("nohup locust -f open_person_backend.py --slave --master-host=172.26.12.128 >>slave.log &")
|
性能调优
系统优化
数据库优化
应用程序优化
- 业务流程优化:异步处理
- JVM优化:内存泄漏、内存溢出