来源商业新知网,原标题:十面九问的逆天异步神器-celery,你了解多少?前端
celery是什么,有什么用?python
对于celery,各类文档解释一堆,能够本身看下,根据平常互动,公众号用户小白居多,官方用到的不少名词可能你理解起来不是那么容易,我这里就不照本宣科了,就以我这边的理解简单如下方图示解释下,若是有误,欢迎指正:web
首先理解一个概念: 阻塞redis
理解阻塞,先从耗时操做讲起,常见的场景好比用户输入、等待(sleep)这些都属于,具体到实际项目中好比说发邮件、发短信、机器/深度学习训练模型、自动化测试中的各类操做流程等待都会产生耗时,耗时操做一般咱们也会称之为阻塞,意思就是程序一行一行代码执行,你这些耗时操做没执行完毕,后面的代码就不会执行,阻塞了后面的代码执行chrome
理解了阻塞之后,就很容易引出一个问题?我若是想提升程序执行效率不让程序阻塞,那该怎么办?有没有一种方式,能在程序阻塞的时候,不影响我后面代码的执行?数据库
通常来讲,咱们能够用线程、进程、协程,都是能够实现的,只不过在实际项目中,有成熟开源而且普遍应用的的东西,咱们会用框架,而不去手写多线程、进程、协程,也不是说这些不用去学,这是编程的基本知识,也是必须掌握的,很能体现编程基本功底django
celery基本原理:编程
一、客户端也就是python(django/flask等)发布任务flask
二、发布的任务存到任务队列里面,能够以redis、rabbitMQ、MessageQueue、MySQL存储,通常在django/flask程序里redis居多后端
三、任务处理者会不断从任务队列里面获取任务执行
一、安装django/celery库
django==2.0.6
celery==3.1.26
django-celery==3.3.0
redis==2.10.6
都用pip安装,我这边这几个版本测试没问题,版本有些时候不兼容,若是报错,网上找下解决
二、redis数据库安装
redis安装:http://www.python88.cn/book/redis10/
注意如下几点:
一、redis.conf改bind127.0.0.1为bind 真实ip,这样能够远程访问
二、若是是阿里云服务器,须要在控制台将6379端口开放
三、redis启动服务端:redis-server,启动客户端:redis-cli
三、演示代码demo
总体流程是在前面页面点击表格里面的执行,会用selenium打开浏览器,执行耗时操做,至关于每一个执行都是一个单独耗时任务
四、demo前端代码:
给按钮绑定run_case2方法,获取当前表格行号(映射要用selenium打开的网站连接),做为参数传到后端
function run_case2(obj){
row_tr = obj.parentNode.parentNode.rowIndex;//获取当前行数
console.log(row_tr);
param = {"url":row_tr};
$.post('/web/yzm/', param, function (data) {
console.log(data.result)
})
}
五、demo后端代码:(阻塞写法)
看下面代码,前端传的行号,我这只是为了测试传参数,随便构造的,分别跟3个网址进行映射,对于下面的这种写法,就是典型的阻塞线程,webdriver在执行的时候,只有当把quit()关闭浏览器执行完毕时候,才会return返回结果并在控制台打印success,以下图演示,我点击的是第三个执行按钮
from selenium import webdriver
import time
@csrf_exempt
@login_required
def yzm(request):
url_num = request.POST.get("url")
if int(url_num)==1:
url_str = "https://www.baidu.com"
elif int(url_num==2:
url_str = "http://www.python66.cn"
elif int(url_num)==3:
url_str = "http://www.python88.cn"
print(url_num,url_str)
# 下面webdriver打开网站,并休眠5秒钟都是耗时任务
driver = webdriver.Chrome(executable_path="C:chromedriver_win32chromedriver.exe")
driver.get(url_str)
time.sleep(5)
driver.quit()
# 耗时任务执行完毕开始return
return JsonResponse({"result": "success"})
六、demo后端代码:(celery异步)
异步: 名字虽然为异步,你能够理解为同步,就是一边作耗时操做,通常执行后面代码,二者同时执行
文件目录,我在项目目录下面创建了celery_task包,建立tasks.py文件
一、建立app,表明一个celery对象,broker表明队列,用的redis 0号数据库
二、而后将上一步咱们selenium打开浏览器的方法封装成open_url方法
三、@app.task表明定义任务,指明这个open_url方法是一个任务,能够在视图里面调用发布
from celery import Celery
from selenium import webdriver
import time
# 建立celery的应用
app = Celery("celery_task", broker="redis://47.101.203.45:6379/0")
@app.task
def open_url(url):
driver = webdriver.Chrome(executable_path="C:chromedriver_win32chromedriver.exe")
driver.get(url)
time.sleep(5)
driver.quit()
views.py视图里面这样写
一、from celery_task.tasks import open_url为导入任务
二、open_url.delay(url_str)为发布任务,其中delay里面能够传参数,你前端传过来的参数views.py视图函数接收,能够再传到celery任务中去
效果图以下:当点击执行时候,return的success很快就返回并打印了,跟我操控浏览器的过程没一点牵涉,无需等待selenium,这样就实现了非阻塞异步,完美解决了耗时问题
from celery_task.tasks import open_url
@csrf_exempt
@login_required
def yzm2(request):
url_num = request.POST.get("url")
if int(url_num)==1:
url_str = "https://www.baidu.com"
elif int(url_num)==2:
url_str = "http://www.python66.cn"
elif int(url_num)==3:
url_str = "http://www.python88.cn"
print(url_num,url_str)
open_url.delay(url_str)
return JsonResponse({"result":"success"})
七、多个任务同时执行
对于多个任务同时执行,我这里连续点击三个执行按钮,立马先打印了3个success,说明3个任务都被celery异步处理了,对于多任务的参数问题,上面也说了,咱们在delay里面传入参数便可,传到定义任务的tasks.py文件里面的对于方法中去,本例中我演示的是传了一个url_str参数
八、启动程序
打开两个终端,都切换到项目目录下面
一、先启动celery:
celery -A celery_task.tasks worker -l info
二、再启动django:
python manage.py runserver
本文重要的是理解原理,celery的牛逼远不止于此,有兴趣能够看看在爬虫、机器学习、深度学习领域的使用,会对celery的使用场景有更清晰的认识