RabbitMQ示例
在MQ之前,我一直使用的redis作为中间人broker然后用celery执行耗时任务。从未在python项目中使用过MQ。所以今天就在django中用RabbitMQ取代redis+celery。
django中使用RabbitMQ:
本次使用RabbitMQ完成点击注册后给用户发送激活邮件的场景,如果不使用MQ,或者不使用异步的方式,后端就会一直等待smtp服务器把邮件发到用户邮箱后才往下走(我们用time.sleep(5)来模拟一下发邮件的耗时)。由于就这一个消息类型,我们就用个简单模式,请看上一期RabbitMQ的六种模式:
1、django中的发送邮件配置
:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' # 固定写法 EMAIL_HOST = 'smtp.qq.com' # QQ的SMTP地址,是163邮箱则换为smtp.163.com EMAIL_PORT = 25 # SMTP端口 EMAIL_HOST_USER = 'aaaaaa@qq.com' #发送邮件的邮箱 EMAIL_HOST_PASSWORD = 'aaaaaaaaaaaaa' # 授权码,qq邮箱中发短信后获取到的 # 发件人,<>里面的东西必须和EMAIL_HOST_USER(目的邮箱地址一摸一样,不能随便写,不然邮件发不出去) EMAIL_FROM = '买了佛冷<aaaaaa@qq.com>'
2、在项目中定义一个类,把email塞进MQ的操作放在构造方法中,到时只需RabbitMQ(email)即可
:
import pika class RabbitMQ(): def __init__(self,email): # 1、连接rabbitmq服务器 connection = pika.BlockingConnection(pika.ConnectionParameters('x.x.x.x')) channel = connection.channel() # 2、创建一个名为hello的队列 channel.queue_declare(queue='hello') # 3、简单模式,向名为hello队列中插入用户邮箱地址email channel.basic_publish(exchange='', routing_key='hello', body=email, ) print("发送用户邮箱:‘{}’ 到MQ成功".format(email)) connection.close()
3、定义一个base.py文件用于导入django环境
,离线脚本初始化用户数据的时候就需要导入django环境,我们的消费者端要使用django的send_mail函数,所以也要导入django环境。
import os import sys import django base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(base_dir) os.environ.setdefault("DJANGO_SETTINGS_MODULE", "你的项目名.settings") django.setup() # os.environ['DJANGO_SETTINGS_MODULE']
4、编写消费者端代码
:
消费者端监听hello队列,在接收到用户的email后,执行回调callback(发邮件操作),回调中模拟了发邮件的等待时间time.sleep(5)
。稍后前端点击注册的时候,观察是否为立即跳转,如果立即跳转就说明MQ是异步,只管塞消息不管处理和处理结果。
# base.py文件用于导入django环境,离线脚本初始化用户数据的时候就需要导入django环境 import base import pika import time from django.core.mail import send_mail from django_MQ_demo import settings # 1、连接rabbitmq服务器 connection = pika.BlockingConnection(pika.ConnectionParameters(host='x.x.x.x')) channel = connection.channel() # 2、创建队列,可以只让一方创建,主要是分不清哪边先跑起来,所以这儿也要创建同样的队列 channel.queue_declare(queue='hello') # 3、构建回调函数 def callback(ch,method,properties,email): print("消费者端收到用户邮箱 ‘{}’ 成功".format(email)) subject = 'lanyc注册' message = '' sender = settings.EMAIL_FROM receiver = [email] # 讲道理还应该来一个html_message,内容为一个激活链接的a标签 # send_mail是django内置的发邮件函数,这四个是必须参数 send_mail(subject, message, sender, receiver) time.sleep(5) print('向目的邮箱{}发送邮件成功'.format(email)) # 发送应答信号,表明数据已经处理完成,可以删除,和auto_ack=False套起来用 ch.basic_ack(delivery_tag=method.delivery_tag) # 确定监听队列:hello,一旦有值出现,则触发回调函数:callback channel.basic_consume(queue='hello', auto_ack=False, on_message_callback=callback, ) print('当前MQ简单模式正在等待生产者往消息队列塞消息.......要退出请按 CTRL+C.......') channel.start_consuming()
5、前端代码
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | <! DOCTYPE html> < html lang="en"> < head > < meta charset="UTF-8"> < title >注 册</ title > </ head > < body > < form id="registerForm"> {% csrf_token %} {% for field in form %} {{ field.label }}:{{ field }}< br > {% endfor %} < input type="button" id='regForm' value="注 册"> </ form > </ body > < script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></ script > < script > $(function () { registerFunc(); }); function registerFunc() { //注册按钮绑定 $('#regForm').click(function () { $.ajax({ url:'/email', method:'post', dataType:'json', //带上用户提交的所有表单信息 data:$('#registerForm').serialize(), success: function (res) { if (res.status){ alert('注册成功!点击确定跳转到邮箱登录页面,请点击您的邮件完成激活'); location.href=res.data; }else{ alert("注册失败") } } }) }) } </ script > </ html > |
6、django后端代码
(还要配路由):
# 路由:/email class UserModelForm(ModelForm): class Meta: model = UserInfo fields = "__all__" def register_email(request): if request.method == "GET": # 要写个form类 form = UserModelForm() return render(request,'register.html',{'form':form}) if request.method == "POST": email = request.POST.get('email') # 实例化上面定义的生产者方的类,自动执行其构造方法,塞email进队列 RabbitMQ(email) # 1、将用户提交的邮箱地址传入RabbitMQ队列------->2、消费端一直等待,就直接取过该队列消息,处理,给用户发送消息
return JsonResponse({'status':True,'data':'https://mail.163.com/'}) return JsonResponse({'status':False})
先运行消费者端代码:
后端的form类中这两个字段我都没写校验钩子只用来生成表单。所以不填用户名没报错,这不是重点。重点是我点击注册后,ajax的post请求会走到后端的RabbitMQ(email)这行代码,执行类中自定义的构造方法塞email进消息队列,塞完email马上返回JsonResponse,不会去等消费者中回调函数的time.sleep(5)模拟时间以及真实发邮件花费的时间。所以页面效果是马上弹出模态框。
163邮箱收到邮件:
消费者端控制台 :
这就是整个django中使用rabbitmq,整个过程就是实现了异步,解耦。后端发邮件只需塞email进MQ,然后就return。如果在后端中直接调用发邮件函数send_mail,就要等着邮件发出去才会return。
文章来源:https://blog.csdn.net/qq_37623764/article/details/105825554
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!