秒殺系統Web實踐——04壓力測試(性能測試JMeter)

第四章秒殺壓測

目錄

第四章秒殺壓測

1.SpringBoot打包

1.1SpringBoot打jar包

1.2SpringBoot打war包

2.JMeter

2.1Windows下使用

2.2命令行下使用

3.自定義變量模式多用戶

4.Redis壓測工具redis-benchmark

綜述


1.SpringBoot打包

1.1SpringBoot打jar包

注意把packaging標籤改爲jar,此標籤也可不寫,springboot默認打包方式爲jar。

<groupId>com.example</groupId>
<artifactId>springboot-upload</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
//注意把packaging標籤改爲jar,此標籤也可不寫,默認打包方式爲jar。
 
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <fork>true</fork>
            </configuration>
        </plugin>
    </plugins>
</build>

使用idea打包: 在IDEA右側Maven Projects欄雙擊package等待Build Success即可

使用命令行打包:

a.黑窗口cd到根目錄(和pom.xmltarget同級),也可在idea工具中選擇Terminal

  b.執行打包命令 mvn clean package (跳過測試類命令 mvn clean package -Dmaven.test.skip=true)

c.打包成功結果如下

運行jar包

java -jar jar包的名字.jar

1.2SpringBoot打war包

pom.xml中把jar改成war,並且添加外置tomcat依賴

<packaging>war</packaging>

<!--打包時排除tomcat-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>

在這裏將 scope屬性設置爲provided,這樣在最終形成的 WAR 中不會包含這個JAR包,因爲TomcatJetty等服務器在運行時將會提供相關的API類。

在入口類中繼承SpringBootServletInitializer並重寫configure方法

@SpringBootApplication
public class SpringbootUploadApplication extends SpringBootServletInitializer {
 
    public static void main(String[] args) {
        SpringApplication.run(SpringbootUploadApplication.class, args);
    }
 
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder){
        return builder.sources(SpringbootUploadApplication.class);
    }
}

輸入命令 mvn clean package打包,把target目錄下生成的war放到tomcatwebapps目錄下即可。

運行tomcat就可以訪問了

2.JMeter

2.1Windows下使用

基本結構有一個線程組包含:HTTP請求,HTTP請求默認值,CSV數據文件設置,聚合報告等。我們接下來說一下常用的操作。

線程組:可以設置線程數和循環次數

HTTP請求默認值:常用於設置域名或ip、端口號、協議,還可以添加參數

聚合報告:會顯示吞吐率也就是我們常說的QPS

CSV數據文件設置:從文件中讀取數據

數據文件如圖

而對應改變的就是http請求的參數

2.2命令行下使用

1.在windows下錄製好jmx,上傳(設置好所用請求和參數)

2.命令行:sh jmeter.sh -n -t XXX.jmx -l result.jtl

3.把result.jtl導入jmeter

3.自定義變量模式多用戶

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.setString(5, user.getPassword());
			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("D:/tokens.txt");
        if(file.exists()) {
            file.delete();
        }
        //RandomAccessFile
        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
            HttpURLConnection co = (HttpURLConnection)url.openConnection();
            co.setRequestMethod("POST");
            co.setDoOutput(true);
            OutputStream out = co.getOutputStream();
            String params = "mobile="+user.getId()+"&password="+MD5Util.inputPassToFormPass("123456")+"&ifyzm=2";
            out.write(params.getBytes());
            out.flush();
            InputStream inputStream = co.getInputStream();
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            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());
            System.out.println(response);
            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(row.getBytes());
            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);
    }
}

4.Redis壓測工具redis-benchmark

Redis 自帶了一個叫 redis-benchmark 的工具來模擬 N 個客戶端同時發出 M 個請求。 你可以使用 redis-benchmark -h 來查看基準參數。

以下參數被支持:
 
Usage: redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests]> [-k <boolean>]
 
 -h <hostname>      Server hostname (default 127.0.0.1)
 -p <port>          Server port (default 6379)
 -s <socket>        Server socket (overrides host and port)
 -a <password>      Password for Redis Auth
 -c <clients>       Number of parallel connections (default 50)
 -n <requests>      Total number of requests (default 100000)
 -d <size>          Data size of SET/GET value in bytes (default 2)
 -dbnum <db>        SELECT the specified db number (default 0)
 -k <boolean>       1=keep alive 0=reconnect (default 1)
 -r <keyspacelen>   Use random keys for SET/GET/INCR, random values for SADD
  Using this option the benchmark will expand the string __rand_int__
  inside an argument with a 12 digits number in the specified range
  from 0 to keyspacelen-1. The substitution changes every time a command
  is executed. Default tests use this to hit random keys in the
  specified range.
 -P <numreq>        Pipeline <numreq> requests. Default 1 (no pipeline).
 -q                 Quiet. Just show query/sec values
 --csv              Output in CSV format
 -l                 Loop. Run the tests forever
 -t <tests>         Only run the comma separated list of tests. The test
                    names are the same as the ones produced as output.
 -I                 Idle mode. Just open N idle connections and wait.

1.redis-benchmark -h 127.0.0.1 -p 6379 -c 100 -n 100000

向127.0.0.1的6379端口,100個併發連接,100000個請求

2.redis-benchmark -h 127.0.0.1 -p 6379 -q -d 100

存取大小爲100字節的數據包

3.redis-benchmark -t set,lpush  -q -n 100000

只測試部分操作

4.redis-benchmark -n 100000 -q script load "redis.call('set','foo','bar')" 

只測試某些數值存取的性能


綜述

這一章節我們瞭解了JMeter,我們使用JMeter測試發現在目前,接口性能較差,QPS較低。我們使用redis-benchmark發現,redis的性能比數據庫更加快速,說以,我們下一章節將對性能方面進行優化

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章