mirror of https://github.com/qiurunze123/miaosha
jmeter压测
parent
9c26d6f579
commit
e230b55c4e
|
@ -40,7 +40,7 @@
|
|||
| ID | Problem | Article |
|
||||
| --- | --- | :--- |
|
||||
| 000 |如何解决卖超问题 | [解决思路](/docs/code-solve.md) |
|
||||
| 001 |如何对本项目进行jmeter压测 | [解决思路](/docs/code-solve.md) |
|
||||
| 001 |如何对本项目进行jmeter压测 | [解决思路](/docs/jemter-solve.md) |
|
||||
| 003 |全局异常处理拦截 |[解决思路](/docs/code-solve.md) |
|
||||
| 003 |页面级缓存thymeleafViewResolver |[解决思路](/docs/code-solve.md) |
|
||||
| 004 |对象级缓存redis🙋🐓 |[解决思路](/docs/code-solve.md) |
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
### 如何利用jmeter进行压测
|
||||
|
||||
有问题或者宝贵意见联系我的QQ,非常希望你的加入!
|
||||
|
||||
>目标 (希望大家仔细研究redis.conf配置文件-本文很多基础的一带而过)
|
||||
|
||||
1.如何对秒杀生成大数据量对应的用户id和token来进行压测
|
||||
2.利用jmeter进行接口压测
|
||||
|
||||
我这个版本只是简单的测试,你仍然需要把一些接口安全的放开或者自己写一个没有安全性防刷一类的接口测试性能
|
||||
|
||||
如果有疑问或者你不懂的地方请联系我!
|
||||
|
||||
#### 1 利用jmeter进行接口压测 (jmeter3.0 jdk1.7 版本以上需1.8 版本在tools里面)
|
||||
|
||||
|
||||
**秒杀生成大数据量对应的用户id和token**
|
||||
|
||||
在后端写模拟前端请求计算出不同的用户对应的token , 在UserUtil类里面
|
||||
|
||||
生成文件格式:
|
||||
![整体流程](https://raw.githubusercontent.com/qiurunze123/imageall/master/jmeter4.png)
|
||||
|
||||
代码类:
|
||||
![整体流程](https://raw.githubusercontent.com/qiurunze123/imageall/master/jmeter2.png)
|
||||
|
||||
![整体流程](https://raw.githubusercontent.com/qiurunze123/imageall/master/jmeter3.png)
|
||||
|
||||
利用这个类可以生成大数据量的userId和token当前也可以自己改装生成你想要的
|
||||
|
||||
|
||||
**利用jmeter进行接口压测**
|
||||
|
||||
1.点击右键生成线程组一类的
|
||||
![整体流程](https://raw.githubusercontent.com/qiurunze123/imageall/master/jmeter5.png)
|
||||
|
||||
2.右键线程组选择配置原件并定义http默认值
|
||||
![整体流程](https://raw.githubusercontent.com/qiurunze123/imageall/master/jmeter6.png)
|
||||
|
||||
3.右键监听器可以生成聚合报告等一类的
|
||||
![整体流程](https://raw.githubusercontent.com/qiurunze123/imageall/master/jmeter7.png)
|
||||
|
||||
4.右键线程组添加sampler 添加请求http请求具体情况更具实际的来
|
||||
![整体流程](https://raw.githubusercontent.com/qiurunze123/imageall/master/jmeter9.png)
|
||||
|
||||
5.右键线程组添加CSV DATA Set Config 设置用户参数和token 把生成的路径引进来
|
||||
![整体流程](https://raw.githubusercontent.com/qiurunze123/imageall/master/jmeter8.png)
|
||||
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
>目标 (希望大家仔细研究redis.conf配置文件-本文很多基础的一带而过)
|
||||
|
||||
2.redis分布式锁,zk分布式锁,lua脚本限流,lua分布式锁
|
||||
3.redis持久化策略
|
||||
4.redis集群
|
||||
5.redis的简单操练
|
||||
1.redis分布式锁,zk分布式锁,lua脚本限流,lua分布式锁
|
||||
2.redis持久化策略
|
||||
3.redis集群
|
||||
4.redis的简单操练
|
||||
整理大部分常用的场景与使用,如果有疑问或者你不懂的地方请联系我!
|
||||
|
||||
#### 1 redis分布式锁
|
||||
|
|
|
@ -37,4 +37,13 @@ public class LoginController {
|
|||
userService.login(response, loginVo);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/create_token")
|
||||
@ResponseBody
|
||||
public String createToken(HttpServletResponse response, @Valid LoginVo loginVo) {
|
||||
logger.info(loginVo.toString());
|
||||
String token = userService.createToken(response, loginVo);
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,11 +62,11 @@ public class MiaoshaController implements InitializingBean {
|
|||
* 5000 * 10
|
||||
* get post get 幂等 从服务端获取数据 不会产生影响 post 对服务端产生变化
|
||||
*/
|
||||
@AccessLimit(seconds = 5, maxCount = 5, needLogin = true)
|
||||
@RequestMapping(value = "/{path}/do_miaosha", method = RequestMethod.POST)
|
||||
// @AccessLimit(seconds = 5, maxCount = 5, needLogin = true)
|
||||
@RequestMapping(value = "/do_miaosha")
|
||||
@ResponseBody
|
||||
public ResultGeekQ<Integer> miaosha(Model model, MiaoshaUser user,
|
||||
@RequestParam("goodsId") long goodsId, @PathVariable("path") String path) {
|
||||
public ResultGeekQ<Integer> miaosha(Model model, MiaoshaUser user, @PathVariable("path") String path,
|
||||
@RequestParam("goodsId") long goodsId) {
|
||||
ResultGeekQ<Integer> result = ResultGeekQ.build();
|
||||
|
||||
if (user == null) {
|
||||
|
@ -89,7 +89,7 @@ public class MiaoshaController implements InitializingBean {
|
|||
// }
|
||||
|
||||
//是否已经秒杀到
|
||||
MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
|
||||
MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(Long.valueOf(user.getNickname()), goodsId);
|
||||
if (order != null) {
|
||||
result.withError(REPEATE_MIAOSHA.getCode(), REPEATE_MIAOSHA.getMessage());
|
||||
return result;
|
||||
|
@ -131,7 +131,7 @@ public class MiaoshaController implements InitializingBean {
|
|||
return result;
|
||||
}
|
||||
model.addAttribute("user", user);
|
||||
Long miaoshaResult = miaoshaService.getMiaoshaResult(user.getId(), goodsId);
|
||||
Long miaoshaResult = miaoshaService.getMiaoshaResult(Long.valueOf(user.getNickname()), goodsId);
|
||||
result.setData(miaoshaResult);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ import java.util.List;
|
|||
@Mapper
|
||||
public interface OrderDao {
|
||||
|
||||
@Select("select * from miaosha_order where user_id=#{userId} and goods_id=#{goodsId}")
|
||||
public MiaoshaOrder getMiaoshaOrderByUserIdGoodsId(@Param("userId") long userId, @Param("goodsId") long goodsId);
|
||||
@Select("select * from miaosha_order where user_id=#{userNickName} and goods_id=#{goodsId}")
|
||||
public MiaoshaOrder getMiaoshaOrderByUserIdGoodsId(@Param("userNickName") long userNickName, @Param("goodsId") long goodsId);
|
||||
|
||||
@Insert("insert into order_info(user_id, goods_id, goods_name, goods_count, goods_price, order_channel, status, create_date)values("
|
||||
+ "#{userId}, #{goodsId}, #{goodsName}, #{goodsCount}, #{goodsPrice}, #{orderChannel},#{status},#{createDate} )")
|
||||
|
|
|
@ -129,6 +129,33 @@ public class MiaoShaUserService {
|
|||
addCookie(response, token, user);
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public String createToken(HttpServletResponse response , LoginVo loginVo) {
|
||||
if(loginVo ==null){
|
||||
throw new GlobleException(SYSTEM_ERROR);
|
||||
}
|
||||
|
||||
String mobile =loginVo.getMobile();
|
||||
String password =loginVo.getPassword();
|
||||
MiaoshaUser user = getByNickName(mobile);
|
||||
if(user == null) {
|
||||
throw new GlobleException(MOBILE_NOT_EXIST);
|
||||
}
|
||||
|
||||
String dbPass = user.getPassword();
|
||||
String saltDb = user.getSalt();
|
||||
String calcPass = MD5Utils.formPassToDBPass(password,saltDb);
|
||||
if(!calcPass.equals(dbPass)){
|
||||
throw new GlobleException(PASSWORD_ERROR);
|
||||
}
|
||||
//生成cookie 将session返回游览器 分布式session
|
||||
String token= UUIDUtil.uuid();
|
||||
addCookie(response, token, user);
|
||||
return token ;
|
||||
}
|
||||
private void addCookie(HttpServletResponse response, String token, MiaoshaUser user) {
|
||||
redisService.set(MiaoShaUserKey.token, token, user);
|
||||
Cookie cookie = new Cookie(COOKIE_NAME_TOKEN, token);
|
||||
|
|
|
@ -53,7 +53,7 @@ public class OrderService {
|
|||
miaoshaOrder.setOrderId(orderInfo.getId());
|
||||
miaoshaOrder.setUserId(user.getId());
|
||||
orderDao.insertMiaoshaOrder(miaoshaOrder);
|
||||
redisService.set(OrderKey.getMiaoshaOrderByUidGid,""+user.getId()+"_"+goods.getId(),miaoshaOrder) ;
|
||||
redisService.set(OrderKey.getMiaoshaOrderByUidGid,""+user.getNickname()+"_"+goods.getId(),miaoshaOrder) ;
|
||||
return orderInfo;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package com.geekq.miaosha.utils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.util.Properties;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.geekq.miaosha.utils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* @author 605162215@qq.com
|
||||
*
|
||||
* @date 2018年1月31日 下午4:32:40<br/>
|
||||
*/
|
||||
public class HttpUtil {
|
||||
public static void main(String[] args) throws Exception{
|
||||
|
||||
for(int i=0;i<10;i++) {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
for(int i=0;i<10;i++) {
|
||||
URL url = new URL("http://192.168.220.130/index.html");
|
||||
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
|
||||
InputStream in = conn.getInputStream();
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
byte[] buff = new byte[1024];
|
||||
int len = 0;
|
||||
while((len = in.read(buff)) >= 0) {
|
||||
bout.write(buff, 0, len);
|
||||
}
|
||||
in.close();
|
||||
bout.close();
|
||||
byte[] response = bout.toByteArray();
|
||||
System.out.println(new String(response, "UTF-8"));
|
||||
Thread.sleep(3000);
|
||||
}
|
||||
}catch(Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.geekq.miaosha.utils;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
public class MD5Util {
|
||||
|
||||
public static String md5(String src) {
|
||||
return DigestUtils.md5Hex(src);
|
||||
}
|
||||
|
||||
private static final String salt = "1a2b3c4d";
|
||||
|
||||
public static String inputPassToFormPass(String inputPass) {
|
||||
String str = ""+salt.charAt(0)+salt.charAt(2) + inputPass +salt.charAt(5) + salt.charAt(4);
|
||||
System.out.println(str);
|
||||
return md5(str);
|
||||
}
|
||||
|
||||
public static String formPassToDBPass(String formPass, String salt) {
|
||||
String str = ""+salt.charAt(0)+salt.charAt(2) + formPass +salt.charAt(5) + salt.charAt(4);
|
||||
return md5(str);
|
||||
}
|
||||
|
||||
public static String inputPassToDbPass(String inputPass, String saltDB) {
|
||||
String formPass = inputPassToFormPass(inputPass);
|
||||
String dbPass = formPassToDBPass(formPass, saltDB);
|
||||
return dbPass;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(inputPassToFormPass("123456"));//d3b1294a61a07da9b49b6e22b2cbd7f9
|
||||
// System.out.println(formPassToDBPass(inputPassToFormPass("123456"), "1a2b3c4d"));
|
||||
// System.out.println(inputPassToDbPass("123456", "1a2b3c4d"));//b7797cce01b4b131b433b6acf4add449
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package com.geekq.miaosha.utils;
|
||||
|
||||
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.geekq.miaosha.domain.MiaoshaUser;
|
||||
|
||||
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(100L+i);
|
||||
user.setLoginCount(1);
|
||||
user.setNickname(String.valueOf(13000000000L+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/create_token";
|
||||
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.getNickname()+"&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 row = user.getNickname()+","+response;
|
||||
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(3);
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ mybatis.config-locations=classpath:mybatis/config.xml
|
|||
#datasource
|
||||
spring.datasource.url=jdbc:mysql://39.107.245.253:3306/miaosha?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
|
||||
spring.datasource.username=root
|
||||
spring.datasource.password=XXXX
|
||||
spring.datasource.password=nihaoma
|
||||
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
|
||||
#druid
|
||||
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
|
||||
|
@ -49,7 +49,7 @@ spring.resources.static-locations=classpath:/static/
|
|||
redis.host=39.107.245.253
|
||||
redis.port=6379
|
||||
redis.timeout=100
|
||||
redis.password=xxxx
|
||||
redis.password=youxin11
|
||||
redis.poolMaxTotal=1000
|
||||
redis.poolMaxIdle=500
|
||||
redis.poolMaxWait=500
|
||||
|
|
Loading…
Reference in New Issue