一、客户端轮询
<script>
function getMiaoshaResult(goodsId){//做一个查询
g_showLoading();//加载中
$.ajax({
url: '/miaosha/result', //
调用后台轮询功能的接口
type: "GET",
data: {//post提交表单的时候,url参数可以放在data中
goodsId: goodsId
//goodsId: $("#goodsId").val()
},
success:function(data){//成功的时候会有一个回调,data是返回的数据,该数据应该是一个对象类型,或字典类型
var result = data.data;
if(data.code == 0){
if(result > 0){//秒杀成功
layer.confirm("秒杀成功,查看订单?",{btn: ["确定","取消"]},
function(){
window.location.href="/order_detail.htm?orderId=" + result;
},function(){
layer.closeAll();
}
);
}else if(result == 0){//排队中
//继续轮询
setTimeout(getMiaoshaResult(goodsId),50);//50毫秒
}else{//秒杀失败
layer.msg("秒杀失败");
}
}else{
layer.msg(data.msg);
}
},
error:function(){
layer.msg("客户端请求有误");
}
});
}
function doMiaosha(){//秒杀的时候,需要向服务端传递参数
$.ajax({
url: '/miaosha/do_miaosha', //
调用后台的实现秒杀功能的接口
type: "POST",
data: {
goodsId: $("#goodsId").val()
},
success:function(data){//成功的时候会有一个回调,data是返回的数据,该数据应该是一个对象类型,或字典类型
if(data.code == 0){
/* render(data.data);//这里需要一个渲染页面的函数 render */
//window.location.href="/order_detail.htm?orderId=" + data.data.id;
getMiaoshaResult($("#goodsId").val());
}else{
layer.msg(data.msg);
}
},
error:function(){
layer.msg("客户端请求有误");
}
});
}
二、后台接口
后台的实现秒杀功能的接口:
@RequestMapping(value="/do_miaosha", method=RequestMethod.POST)
@ResponseBody
public Result<Integer> miaosha(MiaoshaUser user, @RequestParam("goodsId")long goodsId) {
//RequestParam可以把保单隐含提交的input标签对应name属性的元素取出
if(user == null){
return Result.error(CodeMsg.SESSION_ERROR);
}
//判断内存标记
boolean over = isOverMap.get(goodsId);
if(over){
return Result.error(CodeMsg.MIAO_SHA_OVER);
}
//预减库存
long stock = redisService.decr(GoodsKey.getMiaoshaGoodsStock, "" + goodsId);
if(stock < 0){
isOverMap.put(goodsId, true);
return Result.error(CodeMsg.MIAO_SHA_OVER);
}
//判断是否已经进行了秒杀
MiaoshaOrder miaoshaOrder = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(),goodsId);
if(miaoshaOrder != null){
return Result.error(CodeMsg.REPEAT_MIAOSHA);
}
//入队
MiaoshaMessage mm = new MiaoshaMessage();
mm.setMiaoshaUser(user);
mm.setGoodsId(goodsId);
sender.sendMiaoshsaMessage(mm);
return Result.success(0); }
后台轮询功能的接口:
/*
* orderId: 成功
* -1 : 秒杀失败
* 0 : 还在排队
* */
@RequestMapping(value="/result", method=RequestMethod.GET)
@ResponseBody
public Result<Long> result(MiaoshaUser user, @RequestParam("goodsId")long goodsId) {
//RequestParam可以把保单隐含提交的input标签对应name属性的元素取出
if(user == null){
return Result.error(CodeMsg.SESSION_ERROR);
}
//根据result的三种数值范围,来判断下一步的操作
long result = miaoshaService.getMiaoshaResult(user.getId(), goodsId);
return Result.success(result);
}
MiaoshaService:
@Transactional
public OrderInfo miaosha(MiaoshaUser user, GoodsVo goodsVo) {
//减库存(减miaosha_goods的库存), 写入秒杀订单
boolean success = goodsService.reduceStock(goodsVo);
if(success){
//下订单, 包含两步:一、order_info 二、miaosha_order 实际上是两步操作
return orderService.createOrder(user, goodsVo);
}else{//商品已经被秒杀完了
setGoodsOver(goodsVo.getId());
return null;
}
}
public long getMiaoshaResult(Long userId, long goodsId) {
MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(userId, goodsId);
if(order != null){//说明本次查询的时候,已经秒杀成功了
return order.getOrderId();
}else{
boolean isOver = getGoodsOver(goodsId);
if(isOver){
return -1; //代表卖完了
}else{
return 0; //继续轮询
}
} }
private void setGoodsOver(Long id) {
redisService.set(MiaoshaKey.isGoodsOver, "" + id, true);
}
private boolean getGoodsOver(long goodsId) {
return redisService.exists(MiaoshaKey.isGoodsOver, "" + goodsId);
}三、出队
@RabbitListener(queues=MQConfig.MIAOSHA_QUEUE)
public void receiverMiaosha(String message){
logger.info("receiver message: " + message);在接收消息的时候,就可以将字符串转换为对象了,然后对对象进行处理
MiaoshaMessage miaoshaMessage = RedisService.stringToBean(message, MiaoshaMessage.class);
MiaoshaUser user = miaoshaMessage.getMiaoshaUser();
long goodsId = miaoshaMessage.getGoodsId();
//收到消息之后做的事情和controller做的事情是一样的
GoodsVo goodsVo = goodsService.getOneGoodsVoById(goodsId);
int stockCount = goodsVo.getStockCount();
if(stockCount <= 0){
return;
}
//防止一个人秒杀多个商品,判断是否已经秒杀到了 ==> 到OrderService中去查找(查找生成的秒杀类型的订单,这种订单必须是一个用户和一个特价商品关联产生的,且每个用户只能产生一个)
MiaoshaOrder miaoshaOrder = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(),goodsId);
if(miaoshaOrder != null){
return;
}
//减库存,下(写)订单,写入秒杀订单(需要在一个事物当中去做,搞一个service,做一个MiaoshaService,然后进行一个Transaction操作)
OrderInfo orderInfo = miaoshaService.miaosha(user, goodsVo);//为什么成功了以后要返回订单呢?因为我们想秒杀成功之后直接进入到订单详情页
//把订单的详细信息写入到我们的页面上
//return Result.success(orderInfo);
}
python 轮询调度算法
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
权重轮询调度算法 原理 权重约束
如何利用Keras中的权重约束减少深度神经网络中的过拟
权重轮询调度算法 原理 权重 拟合 数据集