秒杀项目04-JMeter压测

1. JMeter入门

1.1 JMeter安装

  1. 官网: http://jmeter.apache.org
    在这里插入图片描述
  2. 下载: http://jmeter.apache.org/download_jmeter.cgi
    在这里插入图片描述
  3. 用户手册 http://jmeter.apache.org/usermanual/index.html
    在这里插入图片描述

1.2 JMeter使用

  1. 首先创建一个线程组
    在这里插入图片描述

  2. 然后在线程组下创建HTTP请求默认值
    在这里插入图片描述

  3. 然后创建HTTP请求在这里插入图片描述

  4. 然后创建监听器
    在这里插入图片描述

1.3 解决一个BUG

UserArgumentResolver.java

private String getCookieValue(HttpServletRequest request, String cookieName) {
        Cookie[] cookies = request.getCookies();
        if (cookies == null || cookies.length <= 0) {
            return null;
        }
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals(cookieName)) {
                return cookie.getValue();
            }
        }
        return null;
    }

查看linux下程序的负载情况,通过top命令

2. 自定义变量模拟多用户

新增UserController

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

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

}

2.1 创建配置文件,里面放userId,userToken的用户信息

config.txt

18936095619,0699ace44abf4611b2b1b2989ada8296

2.2添加配置原件CSV DATA SET CONFIG

在这里插入图片描述

2.3 添加我们刚才编写的配置文件,并完善相关设置

在这里插入图片描述

2.4 在HTTP请求的参数设置中,使用上面定义的变量userToken

在这里插入图片描述

编写程序生成多用户

DBUtil.java

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

UserUtil.java

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("hmxP@ssw0rd");
			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 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();
			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 = bout.toString();
			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);
	}
}

MiaoshaUserService的login方法修改返回值

@Service
public class MiaoshaUserService {

    public static final String COOKIE_NAME_TOKEN = "token";

    @Autowired
    private MiaoshaUserMapper miaoshaUserMapper;

    @Autowired
    private RedisService redisService;

    public MiaoshaUser getByToken(HttpServletResponse response, String token) {
        if (StringUtils.isBlank(token)) {
            return null;
        }
        MiaoshaUser user = redisService.get(MiaoshaUserKey.token, token, MiaoshaUser.class);
        if (user == null) {
            throw new GlobalException(CodeMsg.TOKEN_ERROR);
        }
        //延长token有效期
        addCookie(response,token,user);
        return user;
    }

    public Result<String> login(HttpServletResponse response, LoginVo loginVo) {
        if (loginVo == null) {
            int i = 1;
            throw new GlobalException(CodeMsg.SERVER_ERROR) ;
        }
        String mobile = loginVo.getMobile();
        String formPass = loginVo.getPassword();
        //判断手机号是否存在
        MiaoshaUser user = miaoshaUserMapper.selectById(mobile);
        if (user == null) {
            throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
        }
        //验证密码
        String dbPass = user.getPassword();
        String dbSalt = user.getSalt();
        String pwd = MD5Util.formPassToDBPass(formPass, dbSalt);
        if (!StringUtils.equals(pwd, dbPass)) {
            throw new GlobalException(CodeMsg.PASSWORD_ERROR);
        }
        String token = UUIDUtil.uuid();
        addCookie(response, token, user);
        return Result.success(token);
    }

    //将token返回给浏览器并在redis中添加一份
    private void addCookie(HttpServletResponse response, String token, MiaoshaUser user) {
        //生成token
        //设置redis中token的生存时间与cookie中的一致
        redisService.set(MiaoshaUserKey.token, token, user);
        Cookie cookie = new Cookie(COOKIE_NAME_TOKEN,token);
        cookie.setMaxAge(MiaoshaUserKey.token.expireSeconds());
        cookie.setPath("/");
        response.addCookie(cookie);
    }
}

修改/login/do_login接口的返回值

@RequestMapping("/do_login")
    @ResponseBody
    public Result<String> doLogin(HttpServletResponse response, @Valid LoginVo loginVo) {
        log.info(loginVo.toString());

        //登录
        return miaoshaUserService.login(response, loginVo);
    }

运行在启动应用程序后,启动UserUtil中的主方法生成包含UserId,UserToken的文件。

3. JMeter命令行使用

添加打jar包插件并修改packaging为jar

<packaging>jar</packaging>
<build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

java -jar ***.jar执行流程

首先找到jar包下META-INF目录下的MANIFEST.MF文件
在这里插入图片描述
先走spring提供的main函数再回调我们自己程序的main函数
在这里插入图片描述
将jar包放到linux中并运行nohup java -jar miaosha04.jar &命令,会将日志输出到nohup.out文件中

3.1 在windows上录好jmx

在这里插入图片描述

3.2 上传jmx和jmeter到linux中

3.2 命令行:

运行命令

./apache-jmeter-5.4.1/bin/jmeter.sh -n -t XXX.jmx -l result.jtl

-bash: ./apache-jmeter-5.4.1/bin/jmeter.sh: 权限不够

chmod 777./apache-jmeter-5.4.1/bin/ jmeter.sh 

-bash: ./apache-jmeter-5.4.1/bin/jmeter: 权限不够

chmod 777 ./apache-jmeter-5.4.1/bin/jmeter

通过top命令查看linux负载情况
查看CPU信息
由于是虚拟机,只分配了一个处理器

cat /proc/cpuinfo | grep processor

在这里插入图片描述

3.3 把result.jtl导入到jmeter

通过命令将linux中的文件下载到windows

sz result.jtl

3.4 配置秒杀请求的压测文件

在这里插入图片描述

在这里插入图片描述

将token.txt和压测文件上传到linux中
并且修改压测文件中的token.txt的路径信息

3.5 压测秒杀请求

./apache-jmeter-5.4.1/bin/jmeter.sh  -n -t miaosha.jmx -l result.jtl

将result.jtl下载到windows上,通过jmeter聚合函数查看压测报告
在这里插入图片描述

4. Redis压测工具redis-benchmark

4.1 redis-benchmark -h 127.0.0.1 -p 6379 -c 100 -n 100000 -a 123456 100个并发请求,100000个请求, 密码为123456

在这里插入图片描述

4.2 redis-benchmark -h 127.0.0.1 -p 6379 -q -d 100 -a 123456 存取大小为100字节的数据包

在这里插入图片描述

4.3 redis-benchmark -t set,lpush -q -n 100000 -a 123456 测试set,lpush命令的QPS

在这里插入图片描述

4.4 redis-benchmark -n 100000 -q -a 123456 script load “redis.call(‘set’,‘foo’,‘bar’)” 测试脚本的QPS

在这里插入图片描述

5. SpringBoot打war包

5.1 添加spring-boot-starter-tomcat的provided依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <!--编译时依赖-->
    <scope>provided</scope>
</dependency>

5.2 添加maven-war-plugin插件

<build>
    <finalName>${project.artifactId}</finalName>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
        </plugin>
    </plugins>
</build>

5.3 修改打包方式为war包

<packaging>war</packaging>

5.4 修改启动类

@SpringBootApplication
@MapperScan("com.hmx.miaosha.mapper")
public class MainApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class,args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(MainApplication.class);
    }
}

5.5 在当前文件夹下的cmd窗口中,运行mvn clean package命令

在这里插入图片描述
在这里插入图片描述

5.6 将war包放到本地tomcat的webapps目录中中并启动tomcat

可以通过localhost:8080/miaosha04/login/to_login访问到登录页面
在这里插入图片描述

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值