一、相关库版本信息
python==3.8.13
django==3.2.4
redis==4.1.3
celery==5.2
django-celery-beat==2.2.1
二、Task任务的分类
在程序中,任务大致可以分为同步任务和异步任务两种类型:
同步任务
指的是任务在主线程上需要排队执行的,只有前一个任务执行完毕,才能执行后一个任务。简单点就是说必须 等前一件事做完才能做下一件事。
异步任务
异步任务与同步则是相对的。当我们执行某个任务后,我们并不需要立即得到结果,我们可以正常地做其他操作,或者多次执行任务,这些任务不会等待前一个执行完再去执行,而且可以同时执行的,只需要执行完成后通知或者回调来告诉我们就可以了。
现在我们就是希望在Django框架中通过使用Celery实现异步任务的功能。
三、Celery简介
Celery是一个基于分布式消息传输的异步任务队列,它专注于实时处理,同时也支持任务调度。
Celery的组件介绍:
Beat
:定时地将任务发往消息队列;
Worke
:实时监视消息队列获取队列中的任务执行(可以一个或多个);
Broker
:消息代理,又称消息中间件。就是生产者和消费者存放/拿取产品的地方(消费队列)。Celery目前支持RabbitMQ、Redis、MongoDB、Beanstalk、SQLAlchemy、Zookeeper等作为消息代理,官方推荐 RabbitMQ。
Result Backend
:任务处理完后保存状态信息和结果,以供查询。
四、实现异步任务
项目目录
使用流程:
-
新建一个celery.py文件,此文件跟settings文件同级
代码:import os from celery import Celery from celery.utils.log import get_task_logger from celery.schedules import crontab # Set the default Django settings module for the 'celery' program. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'K_AUTOTESTING.settings') app = Celery('K_AUTOTESTING') # Using a string here means the worker doesn't have to serialize # the configuration object to child processes. # - namespace='CELERY' means all celery-related configuration keys # should have a `CELERY_` prefix. app.config_from_object('django.conf:settings', namespace='CELERY') # Load task modules from all registered Django apps. app.autodiscover_tasks() # 定时任务调度 app.conf.beat_schedule = { "every-midnight-check-account-lock": { 'task': 'get_has_account_lock', "schedule": crontab(minute='*/2'), 'args': () } } @app.task(bind=True) def debug_task(self): print(f'Request: {self.request!r}')
说明:根据实际情况修改项目名称“K_AUTOTESTING”
-
setting文件配置celery相关信息
CELERY_BROKER_URL = os.environ.get('CELERY_BROKER_URL', 'redis://:@127.0.0.1:6379/0') # 存储结果后端 CELERY_RESULT_BACKEND = os.environ.get('CELERY_RESULT_BACKEND', 'redis://127.0.0.1:6379/7') # 时区 CELERY_TIMEZONE = 'Asia/Shanghai' CELERY_TASK_SERIALIZER = 'json' CELERY_TASK_TRACK_STARTED = True CELERY_TASK_TIME_LIMIT = 30 * 60 # redis 相关配置信息 REDIS_HOST = "127.0.0.1" REDIS_PORT = 6379 # 端口 REDIS_PASSWORD = "" REDIS_SSL_STATUS = False # 是否需要SSL REDIS_BASE_URL = "redis://127.0.0.1:6379/" # 基础连接-用于连接池
说明:此处使用redis作为消息队列
-
在子应用下如果需要异步任务,创建task.py文件
importlogging import time from celery import shared_task from k_user import models # 如果logging.getLogger()加上子应用,日志会生成2行一模一样的 logger = logging.getLogger() #测试celery异步 @shared_task def test_celery(str): logger.info('当前已经进入到celery中') time.sleep(5) logger.info('传递过来的值为:%s'%str) logger.info('从celery中出来了') # 定时任务 @shared_task(name="get_has_account_lock") def get_has_account_lock(): # 将所有由于输入密码或验证码次数过多锁定的账户解锁 logger.info("get_has_account_lock starting...") info = models.UserInfo.objects.all().values() print('信息:',info) logger.info("get_has_account_lock end...")
-
在view.py中写视图接口
def celery_test(self, request): test_celery.apply_async(args=['hello,celery']) return Response({ "code": "0001", "success": True, "msg": "定时任务执行成功" })
-
在子应用的urls.py中写接口绑定视图
urlpatterns = [ path('login/', LoginView.as_view()), # 登录 path('register/', RegisterView.as_view()), # 注册 path('user_list/', UserList.as_view({ "get": "get_user_list" })), path('celery_test/', UserList.as_view({ "get": "celery_test" })) ]
-
在managy.py同级开启终端
启动命令:# 如果在linux上启动 celery -A K_AUTOTESTING worker -l INFO & celery -A K_AUTOTESTING beat -l INFO & # 如果在windows上启动 celery -A K_AUTOTESTING worker -l INFO -P eventlet celery -A K_AUTOTESTING beat -l INFO
1、celery高版本不兼容windows,因此需要安装eventlet来兼容windows ,安装命令:pip install eventlet
2、windows在启动celery worker时执行命令式 celery -A K_AUTOTESTING worker -l info -P eventlet -
请求接口执行任务
执行日志,任务成功执行!