基于Jmeter的性能压测平台实现

发表于:2019-5-10 12:03  作者:smooth-z   来源:CSDN

字体: | 上一篇 | 下一篇 |我要投稿 | 推荐标签: Jmeter

  很早就想要一套属于自己的性能压测平台,原因是使用了阿里云的性能测试PTS,就挺羡慕能有一个这样的性能测试平台,但毕竟人家的东西我们高攀不起(要钱的),而且阿里云的性能测试平台是不支持多种协议的(比如我有一个项目要用websocket测试,结果人家就支持http压测)。
  说到开发自己的性能测试平台,肯定想到的是Jmeter,因为开源的性能测试工具没有比它更强大的了,所以第一个想到的是怎么把它变成性能测试平台,很多人首先想到的是通过jenkins结合jmeter,我想那也只能叫调度平台,不能叫性能测试平台。通过对Jmeter和Java快速开发框架的深入了解,我发现做一个自己的性能压测平台是可行的,而且网上也有人正在做。开发的过程肯定是无限的踩坑(开源的东西就这样),相对收获来说应该值的。以下是我针对开源的Java快速开发框架和别人实现的部分成品,再结合JMeterEngine的深入学习,梳理的平台架构:
  以下是主要的技术选型及说明:
  核心框架:Spring Boot 1.5
  安全框架:Apache Shiro 1.3
  视图框架:Spring MVC 4.3
  持久层框架:MyBatis 3.3
  定时器:Quartz 2.3
  数据库连接池:Druid 1.0 (阿里开源)
  日志管理:SLF4J 1.7、Log4j
  页面交互:Vue2.x
  前端监控:ECharts 3.8
  压测内核(即JMeterEngine):Apache JMeter 4.0
  脚本调用内核:Apache Commons Exec 1.3
  远程执行命令:Ganymed build210
  选用的快速框架是经量级的,而且是方便快速部署的:
  【renren-fast开发框架】,具体可以上网获取:https://www.renren.io/guide/
  性能测试平台的项目结构:
  stress-test
  ├─doc  项目SQL语句
  │
  ├─common 公共模块
  │  ├─aspect 系统日志
  │  ├─exception 异常处理
  │  ├─validator 后台校验
  │  └─xss XSS过滤
  │
  ├─config 配置信息
  │
  ├─modules 功能模块
  │  ├─api API接口模块(APP调用)
  │  ├─job 定时任务模块
  │  ├─oss 文件服务模块
  │  ├─sys 权限模块
  │  └─test 压测模块
  │
  ├─RenrenApplication 项目启动类
  │
  ├──resources
  │  ├─mapper SQL对应的XML文件
  │  ├─static 第三方库、插件等静态资源
  │  ├─views  项目静态页面
  │  └─application.yml 环境配置
   平台已实现的部分功能:
  (1)用例管理:
  用例管理支持jmx脚本的上传和参数化文件及测试附件的上传,一个用例创建一个目录(脚本、参数文件、附件、测试报告都在同一用例下保存)。删除用例时会自动删除用例下所关联的脚本,并一并删除已同步到各个节点的文件。
  (2)脚本文件管理
  每个脚本具有启动和停止压测线程的功能(具有状态标识),每个参数化文件或附件具有同步到各个节点的功能(同步完成后标识为同步成功)。
  脚本文件除了启动和停止功能,还能配置是否开启报告生成和是否开户前端监控,监控为echarts图形监控,如下:
  调用脚本进行压测的方法分为两种:
  
  (3)测试报告管理
  
  默认执行脚本过程中,生成了CSV报告,通过【生成报告】按钮,触发将csv报告转换成html DashBoard(这一步也是通过Commons Exec调度jmeter命令完成):
  (4)分布式节点管理
  分布式节点管理通过Ganymed远程执行linux命令,来启动或是停止各节点的Jmeter-server,启动命令格式如下:
   //启动节点
  String enableResult = ssh2Util.runCommand(
  "cd " + slave.getHomeDir() + "/bin/testCases/" + "\n" +
  "sh " + "../jmeter-server -Djava.rmi.server.hostname="+slave.getIp());
  如果是禁用节点,就是通过远程执行杀进程的命令:
  ssh2Util.runCommand("ps -efww|grep -w 'jmeter-server'|grep -v grep|cut -c 9-15|xargs kill -9");
  这种方式挺方便,省了在多台linux节点机上,手动去连接和启动jmeter(分布节点越多越显得方便快捷)。
  另外跟原来相比,分布式节点管理增加了校准功能,就是为了解决节点因为人为因素停了,而管理端不能及时的作出判断,现在通过校准可以将后台节点的进程状态跟前台同步一次(避免进程异常关闭或错误启动),目前不是自动校准。因为无论是实时监听端口还是定时校准,效率都不是最好的。以后可以尝试在压测过程中添加监听机制,来实时监测节点状态,而非压测时段就通过手动点击校准即可,这样会相对经济一些。
  (5)监控扩展(Grafana+InfluxDB)
  由于我在以前的一篇文章中写过有关Grafana+InfluxDB与Jmeter的监控(关于Jmeter长时间压测的可视化监控报告),可以直接拿过来集成使用。集成的方式是开启Grafana的匿名登录(在defaults.ini中配置),到官网下一个Jmeter的监控视图JSON模板导入,同时以跳转的方式将Grafana嵌入到平台的iframe中。
   var URL_IP = parent.location.host;
  var URL_PORT = parent.location.port;
  window.location = "http://"+URL_IP.replace(":"+URL_PORT,"")+":3000/d/joulMbxmz/apache-jmeter-dashboard?orgId=1";
  
   另外可以将Grafana和InfluxDB及一键启动脚本与性能压测平台一起部署,实现在部署层面上进行集成和无缝对接使用。
  写到这我们的性能压测平台前期部分基本介绍完了,还有些功能未开始开发,比如像阿里云PTS的压测场景配置,这比较复杂,相当于是把脚本的场景设置移到WEB界面上,另外还要结合定时器进行脚本的灵活调度(发起压测、结束压测、持续时间、测试周期等),目前来看还没想好怎么实现。但是可以先实现线程组的在线管理:
  (6)线程组管理
  线程组管理的原理也不复杂,就是上传脚本时,通过dom4j递归扫描Jmx脚本(本质上是xml)的节点,获取线程组的配置节点参数,保存入库,然后在界面上修改和管理,改完还可以同步回Jmx脚本(也是通过dom4j对xml进行set配置)。目前实现的管理的线程组类别包括默认的ThreadGroup、jp@gc - Stepping Thread Group、jp@gc - Ultimate Thread Group,这三种已经算最常用的了。线程组管理的目的就是免去简单的线程配置(如并发数配置、线程组禁用)还要线下设置,设置完又要上传,另外脚本的线程组配置在平台界面上也能一目了然,避免又要临时打开Jmeter工具进行查看。
  (7)压测节点监控
  既然有了分布式节点管理,那边我们也可以做到对节点的分布式监控,在Influxdb-Grafana的基础上,引入telegraf来实现;我们通过界面上,加入监控开启和停止的按钮,再结合节点上部署的一些批处理命令,来实现一键启动监控代理。
  启动和关闭的核心代码如下:
   /**
  * 批量切换节点的监控状态
  */
  @Override
  public void updateMonitorBatchStatus(List<Long> slaveIds, Integer monitorStatus) {
  String execStr="";
  for (Long slaveId : slaveIds) {
  StressTestSlaveEntity slave = queryObject(slaveId);
  // 本机节点无需远程操作
  if ("127.0.0.1".equals(slave.getIp().trim())) {
  Runtime r = Runtime.getRuntime();
  //执行本地操作系统命令,不关心返回结果,
  Process p = null;
  try {
  if(OS_NAME_LC.startsWith("windows")){
  if (StressTestUtils.ENABLE.equals(monitorStatus))
  execStr = "cmd.exe /c \""+StressTestUtils.getJmeterHome()+"\\telegraf\\start.cmd\" -a";
  else
  execStr = "cmd.exe /c taskkill /im telegraf.exe /f";
  }else{
  if (StressTestUtils.ENABLE.equals(monitorStatus))
  execStr = "sh "+StressTestUtils.getJmeterHome()+"/telegraf/startUp.sh "+slave.getSlaveName();
  else
  execStr = "sh "+StressTestUtils.getJmeterHome()+"/telegraf/stop.sh "+slave.getSlaveName();
  }
  p = r.exec(execStr);
  p.waitFor();
  } catch (Exception e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
  } finally {
  if(null!=p){
  p.destroy();
  p=null;
  }
  }
  //更新数据库
  slave.setMonitorStatus(monitorStatus);
  update(slave);
  continue;
  }
  //其他节点需要SSH远程连接
  SSH2Utils ssh2Util = new SSH2Utils(slave.getIp(), slave.getUserName(),
  slave.getPasswd(), Integer.parseInt(slave.getSshPort()));
  // 避免跨系统的问题,远端由于都时linux服务器,则文件分隔符统一为/,不然同步文件会报错。
  String telegrafServer = slave.getHomeDir() + "/telegraf/telegraf";
  String md5Str = ssh2Util.runCommand("md5sum " + telegrafServer + " | cut -d ' ' -f1");
  if (!checkMD5(md5Str)) {
  throw new RRException(slave.getSlaveName() + " 监控模块出错!找不到telegraf启动文件!");
  }
  //如果是开启监控
  if (StressTestUtils.ENABLE.equals(monitorStatus)) {
  //启动监控
  execStr =
  "sh " + slave.getHomeDir() + "/telegraf/startUp.sh "
  + slave.getSlaveName()+" "+stressTestUtils.getLocalIp();
  }else{
  //禁用监控
  execStr = "sh " + slave.getHomeDir() + "/telegraf/stop.sh";
  }
  String enableResult = ssh2Util.runCommand(execStr);
  logger.error(enableResult);
  if (!enableResult.contains("telegraf")) {
  throw new RRException(slave.getSlaveName() + " telegraf执行失败!请先尝试在节点机命令执行");
  }
  //更新数据库
  slave.setMonitorStatus(monitorStatus);
  update(slave);
  }
  }
  从代码我们也可以看出,我们将telegraf启动和配置文件都放置在jmeter节点的根目录下,这样能方便远程SSH调用,同时我们将监控平台的IP和节点名称也发送过去,并更新到telegraf.conf文件中,这样启动的telegraf进程就会将监控数据发回到我们的influxdb,并通过grafana监控到。以下是监控的效果:
  这样我们就实现了对压测机的监控(在测试过程中不对压测机监控是不合理的,特别是CPU、内存、网络IO等,万一出现测试机的性能瓶颈由于不能及时发现就会导致无用功),除了压测机的监控,我们可以由点及面,做出一个压测平台的监控服务平台,对被测服务端也进行监控。
  更正说明:写这篇文章的时候,阿里云的PTS刚刚能支持原生jmeter(但前提是有项目支持你花这钱),也就是能支持websocket的压测,具体使用说明他们也提供了教程:https://help.aliyun.com/document_detail/93627.html?spm=5176.7946858.1219570.3.4ced572dQgCraE

    上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。

【大佬说】测试员跳槽时,如何高效地准备面试?

评 论

  • smooth00 (2019-5-13 08:21:49)

    我就是原作者,虽然小编给我留言,但CDSN屏蔽了这个留言,出于我曾经也是51testing的学员,特意来个关注留言。有兴趣的朋友可以关注我的博客。

论坛新帖

顶部 底部


建议使用IE 6.0以上浏览器,800×600以上分辨率,法律顾问:上海瀛东律师事务所 张楠律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2019, 沪ICP备05003035号
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪公网安备 31010102002173号

51Testing官方微信

51Testing官方微博

扫一扫 测试知识全知道