项目地址:https://github.com/wannengdek/spring-boot-seckill

如果项目对您有所帮助,麻烦帮忙点亮小⭐⭐

压力测试

下载工具:https://jmeter.apache.org/download_jmeter.cgi

下载之后解压,点击这个

就出现了

 初步测试结果:

样本代表请求数,我设置的是10000个请求1s 跑完,吞吐量就是并发数,暂时是75,比较小,还需要优化.

 

 

只是读取缓存+写入cookie  所以吞吐量很大

 

模拟秒杀

新建1000个用户,并将他们的token生成到一个文件中,然后使用上面的测试工具来测试.

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 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 = new String(bout.toByteArray());
			JSONObject jo = JSON.parseObject(response);
			String token = jo.getString("data");
			System.out.println("create token : " + user.getId());
//			String token = MD5Util.inputPassToFormPass("123456"+i);
//			String token = UUIDUtil.uuid();
//			System.out.println(MD5Util.inputPassToDbPass("123456"+i, user.getSalt()));
			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(1000);
	}
}

运行主函数之后:

在工具中进行配置:

运行之后:

 

/........................

运行之后不知道咋的,数据崩了,怎么都开不了,修了一下午数据库,总算可以正常使用了

关于数据库的连接问题可以查看这个: https://blog.csdn.net/qq_41852212/article/details/99695878

 

 

再次进行测试:

我设置的是1000个用户抢100件商品  结果  订单超卖

这就是咱们需要解决的并发问题

假设两个线程同时进入到购买界面,但只有一件商品,数据库只能同时卖出,所以就会发生超卖的现象.这就是没有进行处理高并发,多线程所带来的问题.

 

 

以此为基准来进行优化

QPS :1381

5000 * 10

秒杀接口:

QPS: 679

1000*10

 

 

 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐