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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/fk002008/article/details/80207731

         通过上节我们已经可以将用户的信息存入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



运行效果





展开阅读全文

没有更多推荐了,返回首页