商品秒杀功能实现
利用celery模块 异步提交秒杀任务
逻辑:1.前端发送秒杀请求,后端收到请求后异步执行 立即返回前端异步执行任务的id
2.前端设置轮询 每2秒 拿着 任务id 再次请求后端 异步结果接口 查询是否秒杀成功
优点:提高了秒杀的并发,用户所有的秒杀任务都到了异步,可以参与秒杀的人更多了
后端代码:
# 秒杀逻辑分析
后端的情况
1 任务还在等待被执行----》返回给前端,前端继续每隔3s发送一次请求
2 任务执行完了,秒杀成功了---》返回给前端,恭喜您秒杀成功--》关闭前端定时器
3 任务执行完了,秒杀失败了---》返回给前端,秒杀失败--》关闭前端定时器
前端发送请求,带着商品id
返回给后端 异步任务id
http://127.0.0.1:8002/api/v1/home/seckill_text/seckill/?goods_id=1
{ "code": 100,
"msg": "成功",
"result": "34a41591-816a-4688-9751-be81d6ee2d41" }
前端收到任务id号后执行循环任务 每3秒请求一次后端接口 查询是否秒杀成功
http://127.0.0.1:8002/api/v1/home/seckill_text/seckill_result/
?result_id=34a41591-816a-4688-9751-be81d6ee2d41
通过后端返回的code判断异步任务是否结束 未结束继续循环访问
{ "code": 666,
"msg": "等待执行" }
直到后端返回code等于100 关闭定时任务
{ "code": 100,
"msg": "秒杀失败" }
class SeckillView(ViewSet):
@action(methods=['GET'], detail=False)
def seckill(self, request):
goods_id = request.query_params.get('goods_id')
res = seckill_task.delay(goods_id)
return MyResponse(result=str(res))
@action(methods=['GET'], detail=False)
def seckill_result(self, request):
result_id = request.query_params.get('result_id')
res = AsyncResult(id=result_id, app=app)
if res.successful():
result = res.get()
if result:
return MyResponse(msg='秒杀成功')
else:
return MyResponse(msg='秒杀失败')
elif res.failed():
print('任务失败')
elif res.status == 'PENDING':
return MyResponse(code='666',msg='等待执行')
else:
return MyResponse(code='666',msg='执行失败')
前端代码:
前端逻辑:
1 前端秒杀按钮,用户点击---》发送ajax请求到后端
2 视图函数---》提交秒杀任务---》借助于celery,提交到中间件中了
3 当次秒杀的请求,就回去了,携带者任务id号在前端
4 前端开启定时任务,每隔3s钟,带着任务,向后端发送请求,查看是否秒杀成功
<template>
<div>
<button @click="handleSckill">秒杀</button>
</div>
</template>
<script>
import Header from '@/components/Header';
import Banner from '@/components/Banner';
import Footer from '@/components/Footer';
export default {
name: 'Sckill',
data() {
return {
task_id: '',
t: null
}
},
methods: {
handleSckill() {
this.$axios.get(this.$settings.BASE_URL + '/user/sckill/sckill/?
id=1').then(res => {
# 携带商品id 给后端秒杀接口发送请求,获得异步任务id
this.task_id = res.data.task_id
this.t = setInterval(() => {
# 开启循环任务 每2秒发送一次请求
this.$axios.get(this.$settings.BASE_URL + '/user/sckill/get_result/?task_id=' + this.task_id).then(res => {
# 携带任务id向后端发送请求查看任务结果
if (res.data.code == 666) {
# 如果收到后端code为666 则接着循环访问
//如果秒杀任务还没执行,定时任务继续执行
console.log(res.data.msg)
} else {
# 如果后端返回code不是666 则终止循环任务 秒杀结束
// 秒杀结束,无论成功失败,这个定时任务都结束
clearInterval(this.t)
this.t = null
this.$message(res.data.msg)
}
})
}, 2000)
}).catch(res => {
})}}}
</script>
标签:功能,实现,res,前端,任务,秒杀,result,id
From: https://www.cnblogs.com/moongodnnn/p/17203961.html