[转]性能工具之Jmeter通过springboot工程启动


背景

Jmeter平时性能测试工作一般都是通过命令行在linux下执行,为了锻炼自己代码与逻辑能力,想jmeter是否可以通过springboot工程启动,周末在家尝试写一写,一写原来需要处理很多事情,才可以启动起来,起来还是有很问题需要处理,下面是相应的代码,其实网上也有,但关键的是自己有意识收集知识,到用的时候能拿来改一改就用。

启动页面:

前置条件

需要在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-获取启动日志

前端代码

以下参考代码,大家可以学习学习

运行
            停止
            查看信息



后端Controller

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层代码

/**
 * @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();

}

接口实现层

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;
    }


}

工具类

/**
 * 直接执行命令
 *
 * @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中还是一个问题没有解决就是在页面实时参看日志,目前还没实现,不过总体上实现自己想的功能。