前言
项目中经常会遇到一些任务执行时间比较长,比如我司希望通过Web请求调用UG程式进行自动换算并出图的功能,而UG本身应用就比较大,启动耗时较长,再加上每次会发送多条任务,所以每次调用时都需要等待段时间,这样用户体验就不怎么友好,为了加快用户的响应时间,因此决定采用异步方式在后台执行这些任务,celery就是用于处理异步任务的框架。
![0e0d20d84e24f8c0689d101fc674df03.png](https://i-blog.csdnimg.cn/blog_migrate/895d6475a49274d744fa564c873d7f9c.jpeg)
什么是同步、异步
同步:一定要等任务执行完了,得到结果,才执行下一个任务。
异步:不等任务执行完,直接执行下一个任务,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。
什么是Celery
Celery是基于Python开发的简单、灵活且可靠的,能处理大量消息的一个分布式任务队列框架,支持使用任务队列的方式在分布的机器、进程、线程上执行任务调度,同时还支持定时任务。
![735a38aacb55771ac44e7b153a0b82df.png](https://i-blog.csdnimg.cn/blog_migrate/e52d0c8e02cb599ff6f635e23ddedfb1.jpeg)
安装celery
我司项目将redis作为broker,所以需要将redis一起安装,注意我这用的不是django-celery。
pip install celerypip indatll redis
创建celery应用
在ettings同级目录创建一个celery.py文件,引入Celery,然后配置环境变量并创建应用,这里我司将redis作为broker使用了,所以在运行任务前必须先启动redis哦(broker消息队列用于发送和接收消息)。
from celery import Celeryfrom django.conf import settingsimport os# 为celery设置环境变量os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'AIMilling.settings.dev')CELERYD_MAX_TASKS_PER_CHILD = 10# 创建应用app = Celery("demo")# 配置应用app.conf.update( # 配置broker, 这里我们用redis作为broker broker_url='redis://@127.0.0.1:6379/1',)# 设置app自动加载任务# 从已经安装的app中查找任务app.autodiscover_tasks(settings.INSTALLED_APPS)
创建tasks.py文件
在需要使用异步任务的app中创建tasks.py,写入具体的异步任务的方法,这是我司用于调用UG自动生成NC程式的接口方法,使用celery自带的装饰器@task标记函数,这样Celery就知道这一个task方法。
import ctypesfrom AIMilling.celery import app# 创建任务函数from AIMilling.settings.dev import api_path, ug_computer_ipfrom case_manage.models import Program_Path@app.taskdef winfile(prt_file, txt_file, savePath, id): '''向windows發送文件''' lib = ctypes.CDLL('EditCAMParameter.dll') prt_file = bytes(prt_file, encoding='utf-8') txt_file = bytes(txt_file, encoding='utf-8') ip = bytes(ug_computer_ip, encoding='utf-8') b_avePath = bytes(savePath, encoding='utf-8') res = lib.create_ncprg(prt_file, txt_file, b_avePath, ip) if res == 200: Program_Path.objects.filter(id=id).update(status=1) return {ug_computer_ip: 200} return {ug_computer_ip: 400}
触发task任务
在对应的视图中导入tasks中的任务函数调用,然后在调用时加入delay方法来异步处理函数将任务送入broker队列,这样当我们在前端访问该接口时,后台会立即放回response, 从而不阻塞该request, 但任务依旧在后台继续执行中。因为启动时设置了solo模式,所以winfile没有执行完前,即使再次发送执行winfile的任务,celery worker也会等到前一个任务执行完才去执行下一个的。
from case_manage.tasks import winfile # 导入函数res=winfile.delay(prt_path, txt_path, datetime_path, obj.id) # 调用UG程式处理数据
启动redis
下载redis,我直接官方下了一个免安装版的redis,然后解压即可,运行直接进入redis目录打开cmd执行命令:redis-server redis.windows.conf
![4e301aed8b50b903a0fce07e3ae69c36.png](https://i-blog.csdnimg.cn/blog_migrate/9562c8f357698095ca78743b3a063778.jpeg)
启动Celery服务
先启动redis,然后在项目根目录下执行命令:celery -A AIMilling worker --loglevel=info --pool=solo
celery命令解释(查看完整的命令行参数列表 :celery worker --help):
'-A' 是一个全局配置,定义了APP的位置
'--pool' 是POOL的配置,默认是prefork(并发),选择solo之后,发送的任务不会被并发执行,在worker执行任务过程中,再次发送给worker的任务会排队,执行完一个再执行另一个。
欢迎关注本人的公众号:编程手札,文章也会在公众号更新
![81edccc612d8a8b9ddfefeb71a0bf5b5.gif](https://i-blog.csdnimg.cn/blog_migrate/9337215f5b9b00c5c68db34cf7f7cfb3.gif)