优点:
支持并发
中间人broker
可以由redis,RabbitMQ,mongoDB等等,建议RabitMQ稳定性极好。
任务队列
任务队列是一种在线程或机器间分发任务的机制。
消息队列
消息队列的输入是一个工作的单元,独立的(职程)Worker进程持续监视队列中是否由需要处理的新任务。
celery架构由三部分组成:消息中间件(broker),任务执行单元(worker),任务执行结果储存(task store)。
接下来介绍celery和rebbitMQ的使用
安装celery
pip install celery
安装rabbitMQ
pip install redbbitmq-server
docker安装 默认5672端口
sudo docker pull rabbitmq:3-management sudo docker run -d --name rabbit --hostname rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3-management
配置rabbitMQ
sudo rabbitmqctl add_user myuser mypassword sudo rabbitmqctl add_vhost myvhost sudo rabbitmqctl set_user_tags myuser mytag sudo rabbitmqctl set_permissions -p myvhost myuser ".*" ".*" ".*"
使用rabbitMQ的优势
1.从社区活跃度
按照目前网络上的资料,RabbitMQ 、activeM 、ZeroMQ 三者中,综合来看,RabbitMQ 是首选。
2.持久化消息比较
ZeroMq 不支持,ActiveMq 和RabbitMq 都支持。持久化消息主要是指我们机器在不可抗力因素等情况下挂掉了,消息不会丢失的机制。
3.综合技术实现
可靠性、灵活的路由、集群、事务、高可用的队列、消息排序、问题追踪、可视化管理工具、插件系统等等。
4.高并发
毋庸置疑,RabbitMQ 最高,原因是它的实现语言是天生具备高并发高可用的erlang 语言。
5.比较关注的比较, RabbitMQ 和 Kafka
RabbitMq 比Kafka 成熟,在可用性上,稳定性上,可靠性上, RabbitMq 胜于 Kafka (理论上)。
Name | Status | Monitoring | Remote |
---|---|---|---|
RabbitMQ | Stable | Yes | Yes |
Redis | Stable | Yes | Yes |
Zookeeper | Experimental | No | No |
celery在Django中的使用
1.在项目工程文件夹中创建celery文件
2.在celery中编写代码
# 导入新的绝对路径包和文件夹
from __future__ import absolute_import,unicode_literals
import os
# 导入celery框架
from celery import Celery
# 为celery设置django配置文件进行配置
os.environ.setdefault('DJANGO_SETTINGS_MODULE','pro_demo.settings')
# 实例化Celery对象 指定文件
app = Celery('pro_demo')
# 使用这个配置不需要序列化
# 配置子进程对象
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix. 配置必须以 “CELERY_ ”开头
app.config_from_object('django.conf:settings',namespace='CELERY')
# 从django所有应用配置中加载任务模块
app.autodiscover_tasks()
# 开启debug模式
@app.task(bind=True)
def debug_task(self):
print('Request:{}'.format(self.request))
3.在__init__文件中编写代码,这样便于django启动程序时便于加载
from __future__ import absolute_import,unicode_literals
# 这样配置可以保证每次导入模块不出错
# 每次开启celery任务时必须使用shared_task装饰器
from .celery import app as celery_app
# 公开接口 可以是元祖 最好选择列表 在这里我们选择元祖因为官方这么干的
__all__ = ('celery_app',)
这样celery就配置好了 下面写个任务实现一下程序的效果:
1.建立一个demo应用
from __future__ import absolute_import,unicode_literals
from celery import shared_task
from demo_app.models import UserInfo
@shared_task
def add(x,y):
return x + y
@shared_task
def mul(x,y):
return x * y
@shared_task
def count_userinfo():
return UserInfo.objects.count()
@shared_task
def rename_userinfo(user_id,name):
ret = UserInfo.objects.get(id=user_id)
ret.name = name
ret.save()
启动celery
celery -A pro_demo worker -l info
以上demo适合django版本在1.8及更新版本。
在程序中实际应用
例如发送邮件,因为在用户频繁发起邮件请求时,多用户同时请求,容易阻塞,或者服务器宕机,容易让客户体验效果极差。
1.在demo_app中创建tasks.py文件编写发送邮件逻辑
2.编写tasks.py
from __future__ import absolute_import,unicode_literals
from celery import shared_task
from django.core.mail import send_mail
from pro_demo import settings
@shared_task
def send_active_email(email):
subject = "邮件标题"
message = ""
email_list = [email]
from_email = settings.EMAIL_FROM
html_msg = '这是个异步发送测试
'
try:
send_mail(subject=subject,
message=message,
from_email=from_email,
recipient_list=email_list,
html_message=html_msg)
except Exception as e:
print(e)
import json
from django import http
from django.shortcuts import render
# Create your views here.
from django.views import View
from app.demo_app.tasks import send_active_email
class SendEmailDemo(View):
def get(self,request):
# 获取邮箱
data = json.loads(request.body.decode())
email = data.get('email')
# 异步发送邮件
send_active_email.delay(email)
return http.HttpResponse("ok")
4.路由编写
from django.conf.urls import url
from app.demo_app import views
urlpatterns = [
url('^emails/send/',views.SendEmailDemo.as_view())
]
"""pro_demo URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from django.conf.urls import include
urlpatterns = [
url(r'^admin/', admin.site.urls),
# url(r'^',include('app.email_demo.urls')),
url(r'^',include('app.demo_app.urls'))
]
# 导入新的绝对路径包与编码包
from __future__ import absolute_import,unicode_literals
import os
# 导入celery框架
from celery import Celery
# 为celery设置django配置文件进行配置
os.environ.setdefault('DJANGO_SETTINGS_MODULE','pro_demo.settings')
# 实例化Celery对象 指定文件
app = Celery('pro_demo')
# 使用这个配置不需要序列化
# 配置子进程对象
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings',namespace='CELERY')
# 从django所有应用配置中加载任务模块
app.autodiscover_tasks(['app.demo_app'])
@app.task(bind=True)
def debug_task(self):
print('Request:{}'.format(self.request))
# 指定邮件发送后端
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
# 邮件服务器
EMAIL_HOST = 'smtp.163.com'
# smtp 默认端口号是 25
EMAIL_PORT = 25
#发送邮件的邮箱
EMAIL_HOST_USER = '你自己的@163.com'
#在邮箱中设置的客户端授权密码
EMAIL_HOST_PASSWORD = 'xxxxxx'
#收件人看到的发件人
EMAIL_FROM = 'ItCAST邮件测试<你自己的@163.com>'
8.开启celery
celery -A pro_demo worker -l info