谈谈自己为公司设计的jmeter自动化部署框架
一、前言
3/14号收到领导的要求搭建出一套性能自动化部署框架给其它业务线进行使用,接到这个通知当时头也挺大的,去年公司服务上云之前还用过pts那一套产品所以对于性能测试这块还是有些自己的见解,但是呢pts那块的确是贵了点所幸用了目前比较受各中小型企业欢迎的jmeter来作为公司的性能自动化框架。
在说搭建之前我先废话两句谈谈自己对于性能自动化的理解看法
- 对于公司的前后端框架、服务、中间件,DB交互流程你必须有一定的理解,换句话说你应该要知道一个接口的请求下来整体的链路大概是怎样的,这样在你搭建这套部署框架的时候你才能考虑的更周全
- 目前阿里云pts包括其它收费产品都有提供一套性能压测工具,虽然能够做的一定程度的懒人,白痴化但是你要考虑的是公司研发团队的整体成本,开源jmeter框架能否解决目前公司业务所需,如果可以有免费的为何不用?
- 任何自动化测试框架是要能测出问题的,除非你们的产品无任何问题,但是这是不可能的,测不出问题的自动化等于就是玩具毫无作用可言,所以在满足第一条的情况下你才能做够的更多
- 针对本公司中型企业来说日常访问量大概在30W+上下波动,流水大概每天两百万上下,所以说做压测也是有必要的,现在搭起来也能够让公司研发体系的系统架构更加完善
二、部署方案
3/20进行了部署方案的落实,反响还不错都得到领导的认同,也得到一些良好的建议,接下来聊下方案吧
- 此次搭建的是由jmeter+arms进行结合,从而达到输出效果的最大化,以jmeter为触发点,然后用arms对接口进行全链路的监控分析,快速找到系统水位,性能瓶颈
1.arms之前参加过阿里举办的arms大会,现在公司生产环境也正在使用这套产品,效果真的不错全链路监控能够快速的定位到问题的来源,阿里自家淘宝,天猫都是用的这套监控产品
2.arms的压测监控成本也跟运维多多少少聊了一下,以时间跟服务节点数量进行计算,可做的使用开启不用关闭而且一次压测下来也就几十上百RMB的成本还是可以接受的
引入性能测试目的
方案都来源于我们的目标,而目标确是我们做这件事的动力来源,针对本公司我觉得能够带来以下好处(仅简单例举以下几个)
- 深入了解业务各种场景下的性能表现、以及系统的稳定性情况
- 通过性能测试找到前端服务、微服务、中间件、底层DB交互的性能瓶颈,并进行优化
- 对于公司大型系统的架构建立起一套完善的测试指标
- 确定各业务线的性能指标是否符合预期效果
三、部署图
- 测试人员对所需压测的接口进行脚本录制
- 录制脚本放在指定的SVN地址上
- 通过Jenkins选择所需的并发量,循环次数,集合点等场景进行一键触发
- 触发shell脚本的运行
- 触发钩子程序运行对硬件资源实行实时的性能监控报警
- 压测脚本运行结束触发钩子程序终止
- 邮件发送性能测试报告
1.jmeter环境搭建比较简单,在此我就不细说如何搭建的了,网上资料一大把大家可以去搜索,最主要的是大家要会根据公司业务进行灵活运用这才是你应该做的,否则就是玩具毫无意义
2.jenkins环境可以根据我之前文档的总结进行搭建再次我就不叙说了
四、脚本设计
脚本A:
#!/bin/bash
#获取当前进程ID
PID=`echo $$`
bash /data/script/mail-alarm.sh $PID &
#设置基础环境变量及配置
source /etc/profile
jtl=/data/jmeter/result
report=/data/jmeter/report
path=/data/jmeter/jmeters/apache-jmeter-5.1.1/testcase
#htmlPath=/data/jmeter/jmeters/apache-jmeter-5.1.1/jmeter-report/html
#report=/data/workspace/apache-tomcat-8.5.37/webapps/jmeter_report
#rm -rf $htmlPath/*
rm -rf $jtl/*
rm -rf $report/*
rm -rf $path/*
svn checkout svn://[email protected]/project/test/jmeter/ $path/
file=`ls $path/`
string=`echo ${file:0-3}`
dt=`date -d today +"%Y-%m-%d %T"`
#并发和循环次数参数化方法调用
function concurrentAndLoop(){
var1=`cat $path/$file|grep ThreadGroup.num_threads`
var2=`cat $path/$file|grep LoopController.loops`
threads=`echo $var1 |awk -F'>' '{print $2}'`
threadsNum=`echo ${threads%<*}`
loops=`echo $var2 |awk -F'>' '{print $2}'`
loopsNum=`echo ${loops%<*}`
sed -n '/ThreadGroup.num_threads/p' $path/$file |sed "s/$threadsNum/$1/g" $path/$file > $path/case.jmx
sed -n '/LoopController.loops/p' $path/case.jmx |sed "s/$loopsNum/$2/g" $path/case.jmx > $path/case2.jmx
cat $path/case2.jmx > $path/$file
sed -i '1d' $path/$file
sed '1i <?xml version="1.0" encoding="UTF-8"?>' $path/$file
# sed -i 's#<?xml version="2.0" encoding="UTF-8"?>#<?xml version="1.0" encoding="UTF-8"?>#g' $path/$file
rm -rf $path/case.jmx $path/case2.jmx
}
#判断录制脚本是否上传并执行脚本
if [ $string == "jmx" ];then
concurrentAndLoop $1 $2
jmeter -n -t $path/$file -l $jtl/result.jtl -e -o $report/
# cd /data/jmeter/ant/apache-ant-1.9.13/bin;ant
# cd $htmlPath;fileName=`ls TestReport*`
# mv $htmlPath/TestReport* $report/
#邮件发送测试报告
sendEmail -f ***** -s smtp.exmail.qq.com -u "$dt 自动化性能测试报告" -o message-content-type=html -o message-charset=utf-8 -xu ****** -xp ****** -t ****** -m "$dt jmeter性能测试报告结果: *****"
else
echo -e "\033[31;47m 未找到录制的jmx格式脚本文件,请SVN上传jmx格式录制的脚本 \033[0m"
fi
脚本B
#!/bin/bash
#配置基本变量
path1=/data/jmeter/alarm
#获取jmeter.sh脚本运行进程PID
PID=`ps -ef|grep "jmeter.sh" |awk '{if(NR==1){print $2}}'`
while [ $1 -eq $PID ]
do
top -bn 1 > $path1/alarm-report.txt
#获取CPU使用率
CPU=`sed -n 3p $path1/alarm-report.txt |awk -F'us' '{print $1}'`
var=`echo $CPU| awk -F':' '{print $2}'`
CpuValue=`echo $var |awk -F'.' '{print $1}'`
#获取内存使用率值
usedMem=`sed -n 4p $path1/alarm-report.txt|awk -F'used' '{print $1}'|awk -F',' '{print $2}'|awk -F'k' '{print $1}'|awk '{print $1}'`
TotalMem=`sed -n 4p $path1/alarm-report.txt|awk -F'used' '{print $1}'|awk -F'k' '{print $1}'|awk '{print $2}'`
MemValue=`awk 'BEGIN{printf "%.0f\n",('$usedMem'/'$TotalMem'*100)}'`
if [ $CpuValue -ge 90 ]||[ $MemValue -ge 90 ];then
sendEmail -f ******* -s smtp.exmail.qq.com -u "$business压测性能监控报警" -o message-content-type=text -o message-charset=utf-8 -xu ***** -xp Xl123456 -t [email protected] -m "CPU或内存使用率过高,CPU使用率: $CpuValue% Memory使用率: $MemValue%" -a $path/alarm-report.txt
echo -e "\033[31;47m 硬件报警钩子程序终止! \033[0m"
exit 1
fi
sleep 1
#获取最新PID
PID=`ps -ef|grep "jmeter.sh" |awk '{if(NR==1){print $2}}'`
done
echo -e "\033[32;47m 钩子程序运行结束,监控一切正常! \033[0m"
脚本思路分析
- 主要通过脚本A中植入脚本B(A是用来跑jmeter脚本的,B是用来监控服务器硬件资源的)
- 当A脚本运行会触发B的运行
- B会对A进行每个1秒的进程监控,如果进程存在B就会对服务器硬件资源进行持续性监控,存在异常则会进行报警处理
- A脚本运行结束B也随之结束监控
jmeter部署框架大概就此结束了,还要结合云上arms框架对压测服务打入探针才可以进行实时监控,arms那块其实看看官方文档就行,比较简单在此就不多说了