Celery是基于Python的开源分布式任务队列与任务调度系统。
1.什么是任务队列呢?
任务队列是一个将任务分布到多线程或多台机器上的一种机制。一个任务队列的输入(一个任务)是一个工作单元。专用的工作者进程将会持续监控任务队列并执行其中的任务。
2.Celery的模块架构
任务代理/中间人(broker)
celery扮演生产者和消费者的角色,broker就是生产者和消费者存放/拿去产品的地方(任务队列)。任务代理方负责接受任务生产者发送过来的任务消息,存进队列之后再进行调度,分发给任务消费者。因为任务处理是基于消息的,所以我们一般选择RabbitMQ、Redis等消息队列或者数据库作为Celery的message broker。
任务生产者(task producer)
任务生产者(task producer)负责生产计算任务,交由任务队列broker去处理。
任务调度器(celery beat)
celery beat是一个任务调度器,它以独立进程的形式存在。celery beat 进程会读取配置文件的内容,周期性地将任务的请求发送给任务队列。celery beat 是celery系统自带的任务生产者。系统管理员可以选择关闭或开启celery beat。同时在一个celery系统中,只能存在一个celery beat调度器。
任务消费者(celery worker)
celery worker就是执行任务的一方,它负责接收任务代理发送过来的任务处理请求,完成这些任务,并且返回任务处理的结果。celery worker对应的就是操作系统中的一个进程。celery支持分布式部署和横向拓展,我们可以在多个节点增加celery worker的数量来增加系统的高可用性。在分布式系统中,我们可以在不同节点分配不同任务的celery worker来达到模块化的目的。
结果保存(Result Stores / backend)
顾名思义就是结果存放的地方,celery支持任务处理完后将状态信息和结果的保存,以供查询。celery内置支持rpc,django orm,redis,RabbitMQ等方式来保存任务处理后的状态信息。
3.快速开始
以下实例均在Python3.5.3下编译通过。
首先安装celery模块:python3 -m pip install celery
安装redis服务器:apt-get install redis-server
安装python3的redis模块:python3 -m pip install redis
安装request库:python3 -m pip install requests
安装BeautifulSoup:python3 -m pip install bs4
然后,我们先看一个不使用celery的脚本。
#encoding:utf-8
import requests
import time
def func(urls):
start = time.time()
for url in urls:
resp = requests.get(url)
print(resp.status_code)
end=time.time()
return str(end-start)
if __name__ == "__main__":
t=func(["http://www.zhainanbang.net", "http://jd.com", "https://taobao.com", "http://baidu.com", "http://www.secapi.net","http://blog.csdn.net"])
print("耗时:"+t)
接下来,我们我们使用celery,修改下原来的脚本。
#encoding:utf-8
from celery import Celery
import requests
import time
app=Celery('usecelery',broker='redis://localhost:6379/0',backend='redis://localhost:6379/0')
@app.task
def fetch_url(url):
resp=requests.get(url)
print(resp.status_code)
def func(urls):
start = time.time()
for url in urls:
fetch_url.delay(url)
if __name__ == "__main__":
func(["http://www.zhainanbang.net", "http://jd.com", "https://taobao.com", "http://baidu.com", "http://www.secapi.net","http://blog.csdn.net"])
我们需要开3个终端:
第一个终端,运行:redis-server
第二个终端,运行: celery worker -A usecelery -l info -c 10
第三个终端,运行:python3 usecelery.py
我们可以看到输出信息,耗时为0.85秒
上面的这个例子我们只是些了一个celery任务,但是我们可能会有多个任务。因此我们将新建一个celery_config.py
用来配置多个任务。
from celery import Celery
app=Celery('celery_config',broker='redis://localhost:6379/0',backend='redis://localhost:6379/0',include=['usecelery','addcelery'])
我们修改usecelery.py的代码为:
#encoding:utf-8
from celery_config import app
import requests
import time
@app.task
def fetch_url(url):
resp=requests.get(url)
print(resp.status_code)
def func(urls):
start = time.time()
for url in urls:
fetch_url.delay(url)
创建另外一个任务文件adcelery.py,代码如下:
from celery_config import app
@app.taskdef add(a,b):
return a+b
然后我们新建一个task.py文件,用来执行两个任务。代码如下:
from addcelery import add
from usecelery import func
if __name__=='__main__':
func(["http://www.zhainanbang.net", "http://jd.com", "https://taobao.com", "http://baidu.com", "http://www.secapi.net","http://blog.csdn.net"])
for i in range(1,10):
add.delay(i,i%3)
在一个终端中运行:celery worker -A celery_config -l info -c 10
在另外一个终端中执行Python3 task.py
执行效果如下:
那么如何分布式部署呢?我会在下一篇文章中做介绍。