• ▶【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

  • 相关阅读:
    Serverless 架构下的服务优雅下线实践
    容器技术之发展简史
    Fluid 0.3 新版本正式发布:实现云原生场景通用化数据加速
    阿里云研究员叔同:Serverless 正当时!
    精准容量、秒级弹性,压测工具 + SAE 方案如何成功突破传统大促难关?
    如何提升微服务的幸福感?
    Dubbo 3.0 前瞻之:常用协议对比及 RPC 协议新形态探索
    服务发现技术选型那点事儿
    [漫谈] 状态
    [漫谈] 软件设计的目标和途径
  • 原文地址:https://www.cnblogs.com/kirin1105916774/p/15942099.html
Copyright © 2020-2023  润新知