第四章秒殺壓測
目錄
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.xml
、target
同級),也可在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
包,因爲Tomcat
或Jetty
等服務器在運行時將會提供相關的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
放到tomcat
的webapps
目錄下即可。
運行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的性能比數據庫更加快速,說以,我們下一章節將對性能方面進行優化