▶【SecKill】U4 JMeter压测

▶【SecKill】U4 JMeter压测

一、JMeter入门

1、JMeter下载和安装

(1)下载地址:https://jmeter.apache.org/download_jmeter.cgi

 

(2)解压,将 apache-jmeter-5.4.3/bin 下的 jmeter.bat 发送到桌面

(3)启动jmeter.bat

 启动成功!

 

2、术语

QPS(Queries Per Second):每秒查询数,每秒能够响应的查询次数,对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。在因特网上,作为域名系统服务器的机器的性能经常用每秒查询率来衡量。每秒的响应请求数,也即是最大吞吐能力。

 

3、JMeter压测:商品列表

(1)添加 线程组

 

(2)添加 HTTP默认请求

 

(3)添加 HTTP请求

 

(4)添加 聚合报告

 

(5)启动

A. 10个线程:QPS=2.5个/s

Label:请求的名称,就是脚本中Sampler的名称。

#Samples(样本):总共发给服务器的请求数量,如果模拟10个用户,每个用户迭代10次,那么总的请求数为:10*10 =100次。

Average(平均值):默认情况下是单个Request的平均响应时间,当使用了Transaction Controller(事务控制器) 时,也可以用Transaction的时间,来显示平均响应时间 ,单位是毫秒。

Median(中位数):50%用户的响应时间小于该值。

90% Line(90% 百分位):90%用户的响应时间小于该值。

95% Line(95% 百分位):95%用户的响应时间小于该值。

99% Line(99% 百分位):99%用户的响应时间小于该值。

Min(最小值):最小的响应时间。

Maximum(最大值):最大的响应时间。

Error%(异常%):错误率=错误请求的数量/请求的总数。

Throughput(吞吐量):默认情况下表示每秒完成的请求数(Request per Second)。

Received KB/sec (接收数据):每秒从服务器端接收到的数据量。

Sent KB/sec(发送):每秒发送到服务器端的数据量。

 

B. 1000个线程:QPS=200个/s

 

4、检测吞吐量小的原因:数据库

(1)监控服务器的CPU、内存

top

 

(2)同时压测,设置1000*10个线程

发现占用CPU最大的是mysql

 

 

二、自定义变量模拟多用户

1、新建 com.kirin.miaosha.controller 包下 UserController.java(获取用户信息),压测带参用户

package com.kirin.miaosha.controller;

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    MiaoshaUserService userService;
    
    @Autowired
    RedisService redisService;
    
    @RequestMapping("/info")
    @ResponseBody
    public Result<MiaoshaUser> info(Model model,MiaoshaUser user) {
        return Result.success(user);
    }   
}

 

2、自定义变量模拟多用户:获取用户信息

(1)新建 HTTP请求

 

(2)运行系统,做一次商品秒杀,查看后台,找到token值=8da08ab9cff748809c2c1456e0f0c930,填入Jmeter中

 

(3)禁用 “商品列表”HTTP请求

 

(4)压测:QPS高于 “商品列表”HTTP请求

 

3、自定义配置文件JMeter压测

(1)添加 CSV 数据文件设置:配置文件

 

(2)编写配置文件

 

(3)读取我们自己编写的配置文件,并且标注变量名称

 

(4)将数据库的用户信息填入,其中配置文件信息,用英文逗号隔开

 

(5)

 

(6)压测

 

 

三、Linux环境下,JMeter命令行使用

1、打jar包

(1)删除所有打war包的插件、依赖、代码

 

(2)加入jar包依赖

 

(3)打jar包

mvn clean package

 

(4)打开jar包,进入META-INF目录下,打开MANIFEST.MF文件

Main-Class:SpringBoot框架的启动类,在这个类中可以跟进看源码

Start-Class:我们自己编写的启动类

 

2、将项目部署到Linux服务器上 

(1)将jar包上传Linux的tmp文件夹下

(2)将这个进程的输出结果放进nohup.out文件中

nohup java -jar miaosha_2.jar &

 

(3)启动

tail -f nohup.out

访问浏览器

 

★3、压测(起始标准压测数据)

(1)在Windows目录下写好jmx脚本文件

① 设置压测数据

 

② 文件另存为goods_list.jmx,保存到桌面

③ 将jmx脚本文件上传Linux服务器的tmp文件夹下

 

(2)在Linux安装Jmeter

① 将Jmeter放入tmp文件夹下

② 解压

unzip apache-jmeter-5.4.3.zip

 

(3)运行,压测

./apache-jmeter-5.4.3/bin/jmeter.sh -n -t goods_list.jmx -l result.jtl

  -n:不使用图形界面

  -t:不使用config.text脚本文件

  -l:保存输出结果到result.jtl

压测完,生成result.jtl,下载到本地桌面

 

(3)再将result.jtl导入到jmeter的聚合报告中

 

结果1:1.goods_list.jmx

并发10000 = 1000个线程 * 10次循环

QPS=553.2/s

 

结果2:2.miaosha.jmx

并发10000 = 1000个线程 * 10次循环

QPS=146.9/s

A. 添加 com.kirin.miaosha.util / UserUtil.java:生成5000个用户的方法

package com.kirin.miaosha.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kirin.miaosha.domain.MiaoshaUser;

//压测:生成5000个用户的方法
public class UserUtil {
    
    private static void createUser(int count) throws Exception{
        List<MiaoshaUser> users = new ArrayList<MiaoshaUser>(count);
        //生成用户
        for(int i=0;i<count;i++) {
            MiaoshaUser user = new MiaoshaUser();
            user.setId(13000000000L+i);
            user.setLoginCount(1);
            user.setNickname("user"+i);
            user.setRegisterDate(new Date());
            user.setSalt("1a2b3c");
            user.setPassword(MD5Util.inputPassToDbPass("123456", user.getSalt()));
            users.add(user);
        }
        System.out.println("create user");
        //插入数据库
        Connection conn = DBUtil.getConn();
        String sql = "insert into miaosha_user(login_count, nickname, register_date, salt, password, id)values(?,?,?,?,?,?)";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        for(int i=0;i<users.size();i++) {
            MiaoshaUser user = users.get(i);
            pstmt.setInt(1, user.getLoginCount());
            pstmt.setString(2, user.getNickname());
            pstmt.setTimestamp(3, new Timestamp(user.getRegisterDate().getTime()));
            pstmt.setString(4, user.getSalt());
            pstmt.setLong(6, user.getId());
            pstmt.addBatch();
        }
        pstmt.executeBatch();
        pstmt.close();
        conn.close();
        System.out.println("insert to db");
        //登录,生成token
        String urlString = "http://localhost:8080/login/do_login";
        File file = new File("E:/tokens.txt");
        if(file.exists()) {
            file.delete();
        }
        RandomAccessFile raf = new RandomAccessFile(file, "rw");
        file.createNewFile();
        raf.seek(0);
        for(int i=0;i<users.size();i++) {
            MiaoshaUser user = users.get(i);
            URL url = new URL(urlString);
            HttpURLConnection co = (HttpURLConnection)url.openConnection();
            co.setRequestMethod("POST");
            co.setDoOutput(true);
            OutputStream out = co.getOutputStream();
            String params = "mobile="+user.getId()+"&password="+MD5Util.inputPassToFormPass("123456");
            out.write(params.getBytes());
            out.flush();
            byte buff[] = new byte[1024];
            int len = 0;
            while((len = inputStream.read(buff)) >= 0) {
                bout.write(buff, 0 ,len);
            }
            inputStream.close();
            bout.close();
            String response = new String(bout.toByteArray());
            JSONObject jo = JSON.parseObject(response);
            String token = jo.getString("data");
            System.out.println("create token : " + user.getId());
            
            String row = user.getId()+","+token;
            raf.seek(raf.length());
            raf.write("\r\n".getBytes());
            System.out.println("write to file : " + user.getId());
        }
        raf.close();
        
        System.out.println("over");
    }
    
    public static void main(String[] args)throws Exception {
        createUser(5000);
    }
}

 

B. 添加 com.kirin.miaosha.util / DBUtil.java

package com.kirin.miaosha.util;

public class DBUtil {
    
    private static Properties props;
    
    static {
        try {
            InputStream in = DBUtil.class.getClassLoader().getResourceAsStream("application.properties");
            props = new Properties();
            props.load(in);
            in.close();
        }catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public static Connection getConn() throws Exception{
        String url = props.getProperty("spring.datasource.url");
        String username = props.getProperty("spring.datasource.username");
        String password = props.getProperty("spring.datasource.password");
        String driver = props.getProperty("spring.datasource.driver-class-name");
        Class.forName(driver);
        return DriverManager.getConnection(url,username, password);
    }
}

 

C. 修改代码

 

D. 先运行项目,再运行UserUtil.java

E. 新建 HTTP请求

 

F. 新建 CSV 数据文件设置

添加刚刚生成的token.txt

添加参数

另存为miaosha.jmx

 

H. 将miaosha.jmx和tokens.txt上传Linux服务器的tmp文件夹下

I. 修改配置文件中token路径

vi 2.miaosha.jmx

 

J. 压测

./apache-jmeter-5.4.3/bin/jmeter.sh -n -t 2.miaosha.jmx -l result2.jtl

 

 

五、Spring Boot打Jwar包

1、在pom.xml文件中,添加打包为war包的标签

<packaging>war</packaging>

 

2、添加spring-boot-starter-tomcat的provided编译时的依赖

<!-- 10.添加spring-boot-starter-tomcat的provided编译时的依赖:Spring Boot打Jwar包 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-tomcat</artifactId>
  <scope>provided</scope><!-- provided:编译时的依赖 -->
</dependency>

 

3、maven-war-plugin插件

<!-- 10.【Spring Boot打Jwar包】添加spring-boot-starter-tomcat的provided编译时的依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope><!-- provided:编译时的依赖 -->
</dependency>

<finalName>${project.artifactId}</finalName>

<!-- 10.【Spring Boot打Jwar包】添加maven-war-plugin插件 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>                    
    <failOnMissingWebXml>false</failOnMissingWebXml>
    </configuration>
</plugin>
      
<!-- 打jar包插件 -->
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

 

4、在主类 com.kirin.miaosha / MainApplication.java 中,继承SpringBootServletInitializer,重写configure()方法

package com.kirin.miaosha;

@SpringBootApplication
public class MainApplication extends SpringBootServletInitializer{
    public static void main(String[] args) throws Exception {
        SpringApplication.run(MainApplication.class, args);
    }
    
    //Spring Boot打Jwar包:继承SpringBootServletInitializer,重写configure()方法
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(MainApplication.class);
    }
}

 

5、打war包

(1)找到项目目录

 

(2)打war包

mvn clean package

 

(3)将war包放到Tomcat的webapps目录下

(4)启动Tomcat:startup.bat

D:\DevTool\Java\Tomcat\apache-tomcat-8.5.5\bin\startup.bat

 

posted @ 2022-02-27 13:29  淇凌  阅读(122)  评论(0编辑  收藏  举报