记录性能测试的相关知识与实践:测试指标,测试工具,性能调优点

关于性能测试
性能测试是通过自动化的测试工具模拟多种
正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。
负载测试和压力测试都属于性能测试,两者可以结合进行。
- 通过
负载测试,确定在各种工作负载下系统的性能,目标是测试当负载逐渐增加时,系统各项性能指标的变化情况。 压力测试是通过确定一个系统的瓶颈或者不能接受的性能点,来获得系统能提供的最大服务级别的测试。
测试指标
主要是从以下三个维度来衡量
- 响应时间:从用户角度
- Average (ms):服务平均响应时长
- Min (ms):服务最小响应时长
- Max(ms):服务最大响应时长
- 服务器资源:从系统角度
- 内存使用率:内存泄漏,内存溢出
- CPU负载
- 磁盘IO
- 网络IO
- 吞吐量:从业务角度
- Request:总请求数
- RPS(并发数/平均响应时间):服务每秒处理请求数
测试准备工作
工欲善其事必先利其器
服务器监控工具
prometheus.node_exporter系统监控,或者zabbixgrafana可视化
监控指标
- 可用内存
- 可用磁盘
- CPU负载
- 网络流量
JVM监控工具
jps -lvm
查看java进程情况
Java VisualVM
在服务端启动jstatd后,在本地用jdk自带的jvisualvm连接:
- 监控Heap使用情况
- 监控线程情况
测试框架

Locust分布式性能测试框架
- master:1个
- slave:4个
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测试脚本示例
# coding:utf-8
import pandas as pd
import json
import random
import uuid
from locust import HttpLocust, TaskSet, task
class OpenPersonBackendApi(TaskSet):
__PERSON_LIBS = None
# @task(1)
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/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
# ps -ef|grep locust |grep -v grep|awk '{print $2}'|xargs kill
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 &")
性能调优
系统优化
- 连接数
- TCP连接快速回收
数据库优化
- 数据库连接
- 索引命中
- 字段类型
- 读写分离
应用程序优化
- 业务流程优化:异步处理
- JVM优化:内存泄漏、内存溢出