springboot-No10-1:使用JMeter模拟高并发进行压测之应用建立

         通过上节我们已经可以将用户的信息存入redis中,然后通过cookie传给客户端,客户端再进行访问的时候携带这个sessionid然后我们通过HandlerMethodArgumentResolver来获取到用户的信息,并且将用户信息如同Model一样传递给Controller方法.

        这节我们将建立一个秒杀的简单应用,然后我们来模拟高并发.


安装Jmeter

https://jmeter.apache.org/

按照提示安装即可



编写秒杀应用

继续接着我们 spring-boot系列的工程进行编写,代码将会在我的github上面可以看到

我们需要构建如下几个功能:

商品列表,商品详情,秒杀

因此需要建模

商品信息表,秒杀商品信息表,订单表,秒杀订单表

建模

CREATE TABLE `goods` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `goods_name` varchar(45) DEFAULT NULL COMMENT '商品名称',
  `goods_title` varchar(45) DEFAULT NULL COMMENT '商品标题',
  `goods_img` varchar(64) DEFAULT NULL COMMENT '商品的图片',
  `goods_detail` longtext COMMENT '商品详情介绍',
  `goods_price` decimal(10,2) DEFAULT '0.00' COMMENT '商品单价',
  `goods_stock` int(11) DEFAULT '0' COMMENT '商品库存,-1表示没有限制',
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='商品表\n'
CREATE TABLE `miaosha_goods` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '秒杀商品表主键',
  `goods_id` bigint(20) DEFAULT NULL COMMENT '商品id',
  `miaosha_price` decimal(10,2) DEFAULT '0.00' COMMENT '秒杀价',
  `stock_count` int(11) DEFAULT NULL COMMENT '库存数量',
  `start_date` datetime DEFAULT NULL COMMENT '活动开始时间',
  `end_date` datetime DEFAULT NULL COMMENT '结束时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='秒杀商品表'

CREATE TABLE `order_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL COMMENT '用户id',
  `goods_id` bigint(20) DEFAULT NULL COMMENT '商品id',
  `delivery_addr_id` bigint(20) DEFAULT NULL COMMENT '收货地址id',
  `goods_name` varchar(45) DEFAULT NULL COMMENT '冗余过来的商品名称',
  `goods_count` int(11) DEFAULT '0' COMMENT '商品数量',
  `goods_price` decimal(10,2) DEFAULT '0.00' COMMENT '商品单价',
  `order_channel` tinyint(4) DEFAULT '0' COMMENT '购买商品渠道 1 :pc ,2:android,3:ios',
  `status` tinyint(4) DEFAULT '0' COMMENT '订单状态 ,0:新建未支付,1:已支付,2:已发货,3:已收货,4:已退款,5:已完成',
  `create_date` datetime DEFAULT NULL COMMENT '订单创建时间',
  `pay_date` datetime DEFAULT NULL COMMENT '订单支付时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='订单信息表'
CREATE TABLE `miaosha_order` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `user_id` bigint(20) DEFAULT NULL COMMENT '用户id',
  `order_id` bigint(20) DEFAULT NULL COMMENT '订单id',
  `goods_id` bigint(20) DEFAULT NULL COMMENT '商品id',
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='秒杀订单'

建立DAO

GoodsDao.java

package miaosha.dao;



import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import miaosha.dao.domain.MiaoshaGoods;
import miaosha.vo.goods.GoodsVo;

@Mapper
public interface GoodsDao {
	
	/**
	 * 查询2张表的信息使用  GoodsVo来封装2张表的数据
	 * @return
	 */
	@Select("select g.*,mg.stock_count, mg.start_date, mg.end_date,mg.miaosha_price from miaosha_goods mg left join goods g on mg.goods_id = g.id")
	public List<GoodsVo> listGoodsVo();

	/**
	 * 
	 * @param goodsId
	 * @return
	 */
	@Select("select g.*,mg.stock_count, mg.start_date, mg.end_date,mg.miaosha_price from miaosha_goods mg left join goods g on mg.goods_id = g.id where g.id = #{goodsId}")
	public GoodsVo getGoodsVoByGoodsId(@Param("goodsId")long goodsId);

	@Update("update miaosha_goods set stock_count = stock_count - 1 where goods_id = #{goodsId}")
	public int reduceStock(MiaoshaGoods g);
	
}

OrderDao.java

    

package miaosha.dao;



import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.SelectKey;

import miaosha.dao.domain.MiaoshaOrder;
import miaosha.dao.domain.OrderInfo;

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

	@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} )")
	@SelectKey(keyColumn="id", keyProperty="id", resultType=long.class, before=false, statement="select last_insert_id()")
	public long insert(OrderInfo orderInfo);
	
	@Insert("insert into miaosha_order (user_id, goods_id, order_id)values(#{userId}, #{goodsId}, #{orderId})")
	public int insertMiaoshaOrder(MiaoshaOrder miaoshaOrder);

	
}

建立Service

GoodsServiceImpl.java

package miaosha.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import miaosha.dao.GoodsDao;
import miaosha.dao.domain.MiaoshaGoods;
import miaosha.service.GoodsService;
import miaosha.vo.goods.GoodsVo;

@Service
public class GoodsServiceImpl implements GoodsService {
	
	@Autowired
	GoodsDao goodsDao ;

	public List<GoodsVo> listGoods() {
		return goodsDao.listGoodsVo();
	}

	public GoodsVo getGoodsVoByGoodsId(Long goodsId) {
		return goodsDao.getGoodsVoByGoodsId(goodsId);
	}

	public void reduceStock(GoodsVo goods) {
		MiaoshaGoods g = new MiaoshaGoods();
		g.setGoodsId(goods.getId());
		goodsDao.reduceStock(g);
	}

}

OrderServiceImpl.java

package miaosha.service.impl;

import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import miaosha.dao.OrderDao;
import miaosha.dao.domain.MiaoshaOrder;
import miaosha.dao.domain.OrderInfo;
import miaosha.dao.domain.User;
import miaosha.service.OrderService;
import miaosha.vo.goods.GoodsVo;

/**
 * 订单服务
 * @author kaifeng1
 *
 */
@Service
public class OrderServiceImpl implements OrderService {

	@Autowired
	OrderDao orderDao;
	
	public MiaoshaOrder getMiaoshaOrderByUserIdGoodsId(Long userId, Long goodsId) {
		return orderDao.getMiaoshaOrderByUserIdGoodsId(userId, goodsId);
	}

	@Transactional
	public OrderInfo createOrder(User user, GoodsVo goods) {
		OrderInfo orderInfo = new OrderInfo();
		orderInfo.setCreateDate(new Date());
		orderInfo.setDeliveryAddrId(0L);
		orderInfo.setGoodsCount(1);
		orderInfo.setGoodsId(goods.getId());
		orderInfo.setGoodsName(goods.getGoodsName());
		orderInfo.setGoodsPrice(goods.getMiaoshaPrice());
		orderInfo.setOrderChannel(1);
		orderInfo.setStatus(0);
		orderInfo.setUserId(user.getId());
		Long orderId = orderDao.insert(orderInfo);
		MiaoshaOrder miaoshaOrder = new MiaoshaOrder();
		miaoshaOrder.setGoodsId(goods.getId());
		miaoshaOrder.setOrderId(orderId);
		miaoshaOrder.setUserId(user.getId());
		orderDao.insertMiaoshaOrder(miaoshaOrder);
		return orderInfo;
	}

}

MiaoshaServiceImpl.java

package miaosha.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import miaosha.dao.domain.OrderInfo;
import miaosha.dao.domain.User;
import miaosha.service.GoodsService;
import miaosha.service.MiaoshaService;
import miaosha.service.OrderService;
import miaosha.vo.goods.GoodsVo;

/**
 * 秒杀服务
 * @author kaifeng1
 *
 */
@Service
public class MiaoshaServiceImpl implements MiaoshaService {
	@Autowired
	GoodsService goodsService;

	@Autowired
	OrderService orderService;

	public OrderInfo miaosha(User user, GoodsVo goods) {
		// 减库存 下订单 写入秒杀订单
		goodsService.reduceStock(goods);
		// order_info maiosha_order
		return orderService.createOrder(user, goods);
	}

}

Controller编写

GoodsController.java 

package miaosha.controller;

import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import miaosha.dao.domain.User;
import miaosha.service.GoodsService;
import miaosha.service.UserService;
import miaosha.util.ConstValue;
import miaosha.vo.goods.GoodsVo;

@Controller
@RequestMapping("/goods")
public class GoodsController {
	
	@Autowired
	private UserService userService ;
	
	@Autowired
	private GoodsService goodsService ;

	/**
	 * 不用WebConfig 进行的参数的获取 User
	 * @param response
	 * @param model
	 * @param cookieUUid
	 * @param paramUuid
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/toListOldSample")
	public String toListOldSample(HttpServletResponse response,Model model,@CookieValue(value=ConstValue.COOKI_NAME_TOKEN,required=false) String cookieUUid,@RequestParam(value=ConstValue.COOKI_NAME_TOKEN , required=false) String paramUuid) throws Exception {
		String uuid = null ;
		if(cookieUUid != null ) {
			uuid = cookieUUid ;
		} else if(paramUuid != null) {
			uuid = paramUuid ;
		} else {
			//uuid丢失了重新到登录页
			return "login";
		}
		User user = this.userService.getByToken(response, uuid);
		model.addAttribute("user", user);
		return "goods_list";
	}
	
	/**
	 * 使用WebConfig,我们做了这个UserArgumentResolver之后的简洁处理
	 * @param model
	 * @param user
	 * @return
	 */
	@RequestMapping("/toList")
	public String toList(Model model , User user) {
		if(user == null) {
			return "login";
		}
		model.addAttribute("user", user);
		//查询商品信息
		List<GoodsVo> goodsList = goodsService.listGoods();
    	model.addAttribute("goodsList", goodsList);
		return "goods_list";
		
	}
	
	@RequestMapping("/to_detail/{goodsId}")
	public String detail(Model model,User user,
    		@PathVariable("goodsId")Long goodsId) {
		
		model.addAttribute("user", user);
		GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
    	model.addAttribute("goods", goods);
    	
    	long startAt = goods.getStartDate().getTime();
    	long endAt = goods.getEndDate().getTime();
    	long now = System.currentTimeMillis();
    	
    	int miaoshaStatus = 0;
    	int remainSeconds = 0;
    	if(now < startAt ) {//秒杀还没开始,倒计时
    		miaoshaStatus = 0;
    		//单位是毫秒
    		remainSeconds = (int)((startAt - now )/1000);
    	}else  if(now > endAt){//秒杀已经结束
    		miaoshaStatus = 2;
    		remainSeconds = -1;
    	}else {//秒杀进行中
    		miaoshaStatus = 1;
    		remainSeconds = 0;
    	}
    	model.addAttribute("miaoshaStatus", miaoshaStatus);
    	model.addAttribute("remainSeconds", remainSeconds);
		return "goods_detail";
	}
}

这里我们主要先压测这个 

toList方法


页面html



运行效果





  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
JMeter 是一款功能强大的开源性能测试工具,可以用于模拟高并发压力测试。以下是 JMeter 高并发压测的一般步骤: 1. 创建测试计划:在 JMeter 中创建一个测试计划,该计划将包含所有需要进行压力测试的请求。 2. 添加线程组:在测试计划中添加一个线程组,用于模拟并发用户。可以设置线程数、启动时间、循环次数等参数。 3. 添加请求:在线程组中添加需要进行压力测试的请求。例如,可以添加 HTTP 请求来模拟用户访问网站的行为。 4. 配置请求参数:对每个请求配置相应的参数,如 URL、请求方法、请求头、请求体等。 5. 添加断言:为了验证响应是否符合预期,可以添加断言来检查响应内容、响应时间等。 6. 配置定时器:通过添加定时器来模拟用户请求的间隔时间,以控制并发量。 7. 配置监听器:添加监听器来收集测试结果,如查看响应时间、错误率、吞吐量等。 8. 运行测试:保存测试计划并运行测试。JMeter模拟并发用户发送请求,收集性能指标,并生成报告。 9. 分析结果:使用 JMeter 提供的报告功能,对测试结果进行分析和解读,以评估应用程序的性能和稳定性。 请注意,在进行高并发压测时,需要考虑目标系统的性能和承受能力,合理设置线程数和循环次数,避免对目标系统造成过大的负担。同时,建议在测试之前先进行预热,模拟逐渐增加的用户负载,以更真实地模拟实际情况。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值