[转]性能工具之Jmeter通过springboot工程启动
背景
Jmeter平时性能测试工作一般都是通过命令行在linux下执行,为了锻炼自己代码与逻辑能力,想jmeter是否可以通过springboot工程启动,周末在家尝试写一写,一写原来需要处理很多事情,才可以启动起来,起来还是有很问题需要处理,下面是相应的代码,其实网上也有,但关键的是自己有意识收集知识,到用的时候能拿来改一改就用。
启动页面:
前置条件
1 2 3 4 5 6 7 8 9 10 11 | 需要在linux中配置Jmeter成功,并且配置环境变量: 环境配置: 编辑: vi ~/.bash_profile #jmeter:路径 根据自己事情情况修改 JMETER_HOME=/root/tools/apache-jmeter- 5.1 . 1 PATH=$PATH:$HOME/bin:$JMETER_HOME/bin: export PATH 执行生效: source ~/.bash_profile |
点击上传脚本,弹出对话框,点击上传,后台日志显示上传成功:
点击启动:并且读取启动日志

点击停止:

上面脚本停止
图画说明:
通过访问--》调用java代码--》启动shell命令--》启动jmeter-获取启动日志
前端代码
以下参考代码,大家可以学习学习
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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | <a class = "btn btn-success" onclick= "JmeterRun()" type= "submit" >运行</a> <a class = "btn btn-danger" onclick= "Jmeterstop()" type= "submit" >停止</a> <a class = "btn btn-info" onclick= "JmeterInfo()" data-toggle= "modal" data-target= "#myModal" >查看信息</a> <script> //上传脚本 function submitupload() { var type = "file" ; //后台接收时需要的参数名称,自定义即可 var id = "jmeterId" ; //即input的id,用来寻找值 var formData = new FormData(); var jmeterId = $( "#jmeterId" ).val(); if (jmeterId == "" ) { layer.msg( "Jmeter文件不能为空,请输入" , {time: 2000 , icon: 5 , shift: 6 }, function () { }); return ; } formData.append(type, $( "#" + id)[ 0 ].files[ 0 ]); $.ajax({ type: "POST" , url: '/jmeter/upload' , data: formData, processData: false , contentType: false , success: function (data) { if (data.code == 100 ) { layer.msg( "用户信息保存成功" , {time: 1000 , icon: 6 }, function () { // console.log("相应结果:" + data.extend.file); //通过返回结果进行赋值 $( "#jmeterName" ).val(data.extend.file); // window.location.href = "/jmeterIndex"; }); } else { layer.msg( "信息保存失败,请重新操作" + data.err, {time: 2000 , icon: 5 , shift: 6 }, function () { }); } } }); } //上传参数 function submitParm() { var type = "file" ; //后台接收时需要的参数名称,自定义即可 var id = "jmeterParam" ; //即input的id,用来寻找值 var formData = new FormData(); var jmeterPara = $( "#jmeterParam" ).val(); if (jmeterPara == "" ) { layer.msg( "Jmeter文件不能为空,请输入" , {time: 2000 , icon: 5 , shift: 6 }, function () { }); return ; } formData.append(type, $( "#" + id)[ 0 ].files[ 0 ]); $.ajax({ type: "POST" , url: '/jmeter/Paramupload' , data: formData, processData: false , contentType: false , success: function (data) { if (data.code == 100 ) { layer.msg( "参数文件保存成功" , {time: 1000 , icon: 6 }, function () { }); } else { layer.msg( "信息保存失败,请重新操作" + data.err, {time: 2000 , icon: 5 , shift: 6 }, function () { }); } } }); } //运行 function JmeterRun() { let JmeterName = $( "#jmeterName" ).val(); let number = $( "#numberName" ).val(); let duration = $( "#duration" ).val(); console.log(JmeterName); console.log(number); $.ajax({ type: "POST" , url: '/jmeter/JmeterRun' , data: { "jmeterName" : JmeterName, "numberName" : number, "duration" : duration }, success: function (result) { if (result.code == 100 ) { layer.msg( "启动成功成功" , {time: 1000 , icon: 6 }, function () { }); } else { layer.msg( "启动失败,请重新操作" , {time: 2000 , icon: 5 , shift: 6 }, function () { }); } } }) } //停止 function Jmeterstop() { $.ajax({ type: "Get" , url: '/jmeter/JmeterStop' , processData: false , contentType: false , success: function (result) { if (result.code== 100 ) { layer.msg( "停止成功" , {time: 1000 , icon: 6 }, function () { }); } else { layer.msg( "停止失败,请重新操作" , {time: 2000 , icon: 5 , shift: 6 }, function () { }); } } }) } //查看日志 function JmeterInfo() { $.ajax({ type: "Get" , url: '/jmeter/Jmeterinfo' , processData: false , contentType: false , success: function (result) { if (result.code == 100 ) { layer.msg( "启动成功成功" , {time: 1000 , icon: 6 }, function () { $( "#JmeterMsg" ).val(data.extend.infopage); }); } else { layer.msg( "启动失败,请重新操作" , {time: 2000 , icon: 5 , shift: 6 }, function () { }); } } }) } </script> |
后端Controller
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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | import com.sevendays.pojo.Msg; import com.sevendays.service.JmerterScriptService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; /** * @author liwen * @Title: JmeterController * @Description: Jmeter启动页面 * @date 2019/11/17 / 10:32 */ @Controller @RequestMapping ( "/jmeter" ) public class JmeterController { private static final Logger logger = LoggerFactory.getLogger(JmeterController. class ); @Autowired JmerterScriptService jmerterScriptService; @GetMapping ( "/jmeterIndex" ) public String jmeterIndex() { return "jmeter/jmterIndex" ; } /** * 上传脚本 * * @param file * @return */ @PostMapping ( "/upload" ) @ResponseBody public Msg upload( @RequestParam ( "file" ) MultipartFile file) { if (file.isEmpty()) { return Msg.fail().add( "err" , "上传失败" ); } String fileName = file.getOriginalFilename(); logger.info( "路径" + fileName); String filePath = "/home/7d/" ; // String filePath = "E:\\test\\7d\\data\\"; if (!fileName.endsWith( ".jmx" )) { return Msg.fail().add( "err" , "脚本上传失败" ); } File dest = new File(filePath + fileName); String jmxName = fileName.substring( 0 , fileName.lastIndexOf( "." )); try { file.transferTo(dest); logger.info( "上传成功:" + jmxName); return Msg.success().add( "file" , jmxName); } catch (IOException e) { logger.error(e.toString(), e); } return Msg.fail(); } /** * 上传参数文件 * * @param file * @return */ @PostMapping ( "/Paramupload" ) @ResponseBody public Msg uploadParam( @RequestParam ( "file" ) MultipartFile file) { if (file.isEmpty()) { return Msg.fail().add( "err" , "上传失败" ); } String fileName = file.getOriginalFilename(); logger.info( "路径" + fileName); String filePath = "/home/7d" ; // String filePath = "E:\\test\\7d\\data\\"; File dest = new File(filePath + fileName); String jmxName = fileName.substring( 0 , fileName.lastIndexOf( "." )); try { file.transferTo(dest); logger.info( "上传成功:" + jmxName); return Msg.success().add( "file" , jmxName); } catch (IOException e) { logger.error(e.toString(), e); } return Msg.fail(); } /** * 运行脚本 * * @return */ @PostMapping ( "/JmeterRun" ) @ResponseBody public Msg run( @RequestParam ( "jmeterName" ) String jmeterName, @RequestParam ( "numberName" ) String numberName, @RequestParam ( "duration" ) String duration) { logger.info(jmeterName); if (!jmeterName.isEmpty() && !numberName.isEmpty()) { jmerterScriptService.runCommand(jmeterName.trim(), numberName.trim(), duration); return Msg.success(); } else { return Msg.fail(); } } /** * 停止脚本 * * @return */ @GetMapping ( "/JmeterStop" ) @ResponseBody public Msg stop() { jmerterScriptService.stopCommand(); return Msg.success(); } /** * 查看日志 * * @return */ @GetMapping ( "/Jmeterinfo" ) @ResponseBody public Msg info() { String info = jmerterScriptService.selectInfo(); return Msg.success().add( "infopage" , info); } } |
interface层代码
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 | /** * @author liwen * @Title: JmerterScriptService * @Description: Jmeterj脚本处理 * @date 2019/11/17 / 18:06 */ public interface JmerterScriptService { /** * 执行命令 * @param cmd */ void execCommand(String cmd); /** * 运行 * @param script 脚本 * @param num 数量 * @param seconds 执行时间 */ void runCommand(String script, String num,String seconds); /** * 停止 */ void stopCommand(); /** * 获取日志 * @return */ String selectInfo(); } |
接口实现层
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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | import com.sevendays.controller.JmeterController; import com.sevendays.service.JmerterScriptService; import com.sevendays.utils.LogSvrReadInput; import com.sevendays.utils.execCmd; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.io.BufferedReader; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Date; /** * @author liwen * @Title: JmerterScriptServiceImpl * @Description: 执行命令 * @date 2019/11/17 / 18:49 */ @Service public class JmerterScriptServiceImpl implements JmerterScriptService { private static final Logger logger = LoggerFactory.getLogger(JmerterScriptServiceImpl. class ); @Override public void execCommand(String cmd) { try { Runtime rt = Runtime.getRuntime(); Process proc = rt.exec(cmd, null , null ); InputStream stderr = proc.getInputStream(); InputStreamReader isr = new InputStreamReader(stderr, "GBK" ); BufferedReader br = new BufferedReader(isr); String line = "" ; while ((line = br.readLine()) != null ) { logger.info(line); } } catch (Exception e) { e.printStackTrace(); } } @Override public void runCommand(String script, String num, String seconds) { String bak = "cp /home/7d/" + script + ".jmx /home/7d/" + script + "bak.jmx" ; String old = "/home/7d/" + script + ".jmx" ; execCmd.execCmd(bak); logger.info( "路径:{}" , old); //替换执行数量 execCmd.replacTextContent(old, "#numThread" , num); //替换执行时间 execCmd.replacTextContent(old, "#timeDuration" , seconds); String runcmd = "nohup jmeter -n -t /home/7d/#scriptName.jmx -l /home/7d/#scriptName.jtl -j /home/7d/jmeter.log > /home/7d/jmeterlog.log&" .replaceAll( "#scriptName" , script); logger.info( "运行命令{}" , runcmd); execCmd.execCmd(runcmd); } @Override public void stopCommand() { String stoprunm = "/root/tools/apache-jmeter-5.1.1/bin/shutdown.sh" ; execCmd.execCmd(stoprunm); } @Override public String selectInfo() { String tail = "tail -f /home/7d/jmeterlog.log" ; File file = new File( "/home/7d/jmeterlog.log" ); String s = LogSvrReadInput.realtimeShowLog(file); logger.info( "输出日志:--》{}" ,s); return s; } } |
工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /** * 直接执行命令 * * @param cmd */ public static void execCmd(String cmd) { try { Runtime rt = Runtime.getRuntime(); Process proc = rt.exec(cmd, null , null ); InputStream stderr = proc.getInputStream(); InputStreamReader isr = new InputStreamReader(stderr, "GBK" ); BufferedReader br = new BufferedReader(isr); String line = "" ; while ((line = br.readLine()) != null ) { logger.info(line); } } catch (Exception e) { e.printStackTrace(); } } |
jmeter脚本:
脚本其实也没有什么东西,只有定义好规则,这样方便替换。
GitHub 地址:
https://github.com/357712148/bodygit.git
小结:
做性能测试代码能力,不是关键,但是是晋升一个必要条件,而且在项目性能分析还是需要懂一些代码能力,这样与研发,DBA、运维能谈的来。
善用时间,珍惜时间意味着生命的延长,人生的卓越。
上面存在的问题:
上面deme中还是一个问题没有解决就是在页面实时参看日志,目前还没实现,不过总体上实现自己想的功能。
标签:
jmeter
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)