在RedHat系Linux上部署Python的Celery框架的教程


Posted in Python onApril 07, 2015

 Celery (芹菜)是基于Python开发的分布式任务队列。它支持使用任务队列的方式在分布的机器/进程/线程上执行任务调度。
架构设计

在RedHat系Linux上部署Python的Celery框架的教程

 Celery的架构由三部分组成,消息中间件(message broker),任务执行单元(worker)和任务执行结果存储(task result store)组成。

1. 消息中间件

    Celery本身不提供消息服务,但是可以方便的和第三方提供的消息中间件集成。包括,RabbitMQ, Redis, MongoDB (experimental), Amazon SQS (experimental),CouchDB (experimental), SQLAlchemy (experimental),Django ORM (experimental), IronMQ

2.任务执行单元

    Worker是Celery提供的任务执行的单元,worker并发的运行在分布式的系统节点中。

3.任务结果存储

    Task result store用来存储Worker执行的任务的结果,Celery支持以不同方式存储任务的结果,包括AMQP, Redis,memcached, MongoDB,SQLAlchemy, Django ORM,Apache Cassandra, IronCache

另外, Celery还支持不同的并发和序列化的手段

1.并发

    Prefork, Eventlet, gevent, threads/single threaded

2.序列化

    pickle, json, yaml, msgpack. zlib, bzip2 compression, Cryptographic message signing 等等

安装和运行

Celery的安装过程略为复杂,下面的安装过程是基于我的AWS EC2的Linux版本的安装过程,不同的系统安装过程可能会有差异。大家可以参考官方文档。

首先我选择RabbitMQ作为消息中间件,所以要先安装RabbitMQ。作为安装准备,先更新YUM。
 

sudo yum -y update

RabbitMQ是基于erlang的,所以先安装erlang
 
# Add and enable relevant application repositories:
# Note: We are also enabling third party remi package repositories.
wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
sudo rpm -Uvh remi-release-6*.rpm epel-release-6*.rpm
 
# Finally, download and install Erlang:
yum install -y erlang

然后安装RabbitMQ
 

# Download the latest RabbitMQ package using wget:
wget 
# Add the necessary keys for verification:
rpm --import 
# Install the .RPM package using YUM:
yum install rabbitmq-server-3.2.2-1.noarch.rpm

启动RabbitMQ服务
 

rabbitmq-server start
RabbitMQ服务已经准备好了,然后安装Celery, 假定你使用pip来管理你的python安装包
pip install Celery

 

为了测试Celery是否工作,我们运行一个最简单的任务,编写tasks.py
 
from celery import Celery
 
app = Celery('tasks', backend='amqp', broker='amqp://guest@localhost//')
app.conf.CELERY_RESULT_BACKEND = 'db+sqlite:///results.sqlite'
 
@app.task
def add(x, y):
 return x + y

在当前目录运行一个worker,用来执行这个加法的task
 

celery -A tasks worker --loglevel=info

其中-A参数表示的是Celery App的名字。注意这里我使用的是SQLAlchemy作为结果存储。对应的python包要事先安装好。

worker日志中我们会看到这样的信息
 

- ** ---------- [config]
- ** ---------- .> app:   tasks:0x1e68d50
- ** ---------- .> transport: amqp://guest:**@localhost:5672//
- ** ---------- .> results:  db+sqlite:///results.sqlite
- *** --- * --- .> concurrency: 8 (prefork)

其中,我们可以看到worker缺省使用prefork来执行并发,并设置并发数为8

下面的任务执行的客户端代码:
 

from tasks import add
import time
result = add.delay(4,4)
 
while not result.ready():
 print "not ready yet"
 time.sleep(5)
 
print result.get()

用python执行这段客户端代码,在客户端,结果如下
 

not ready 
8

Work日志显示
 

[2015-03-12 02:54:07,973: INFO/MainProcess] Received task: tasks.add[34c4210f-1bc5-420f-a421-1500361b914f]
[2015-03-12 02:54:08,006: INFO/MainProcess] Task tasks.add[34c4210f-1bc5-420f-a421-1500361b914f] succeeded in 0.0309705100954s: 8

这里我们可以发现,每一个task有一个唯一的ID,task异步执行在worker上。

这里要注意的是,如果你运行官方文档中的例子,你是无法在客户端得到结果的,这也是我为什么要使用SQLAlchemy来存储任务执行结果的原因。官方的例子使用AMPQ,有可能Worker在打印日志的时候取出了task的运行结果显示在worker日志中,然而AMPQ作为一个消息队列,当消息被取走后,队列中就没有了,于是客户端总是无法得到任务的执行结果。不知道为什么官方文档对这样的错误视而不见。

如果大家想要对Celery做更进一步的了解,请参考官方文档

Python 相关文章推荐
Python中的pprint折腾记
Jan 21 Python
python中常用检测字符串相关函数汇总
Apr 15 Python
举例详解Python中threading模块的几个常用方法
Jun 18 Python
深入讲解Python函数中参数的使用及默认参数的陷阱
Mar 13 Python
Python实现批量检测HTTP服务的状态
Oct 27 Python
python中列表和元组的区别
Dec 18 Python
Python实现学校管理系统
Jan 11 Python
致Python初学者 Anaconda入门使用指南完整版
Apr 05 Python
python 读取txt,json和hdf5文件的实例
Jun 05 Python
python实现控制COM口的示例
Jul 03 Python
python 提取文件指定列的方法示例
Aug 07 Python
使用Python通过企业微信应用给企业成员发消息
Apr 18 Python
详解Python3.1版本带来的核心变化
Apr 07 #Python
初学Python函数的笔记整理
Apr 07 #Python
利用Python绘制数据的瀑布图的教程
Apr 07 #Python
浅析Python中的多进程与多线程的使用
Apr 07 #Python
Python多线程编程(八):使用Event实现线程间通信
Apr 05 #Python
Python多线程编程(七):使用Condition实现复杂同步
Apr 05 #Python
Python多线程编程(六):可重入锁RLock
Apr 05 #Python
You might like
PHP 事务处理数据实现代码
2010/05/13 PHP
php代码书写习惯优化小结
2013/06/20 PHP
Zend Framework框架路由机制代码分析
2016/03/22 PHP
Yii2中cookie用法示例分析
2016/07/18 PHP
php大小写转换函数(strtolower、strtoupper)用法介绍
2017/11/17 PHP
discuz论坛更换域名,详细文件修改步骤
2020/12/09 PHP
总结一些js自定义的函数
2006/08/05 Javascript
js控制div及网页相关属性的代码
2009/12/19 Javascript
JavaScript中判断两个字符串是否相等的方法
2015/07/07 Javascript
jQuery对象与DOM对象转换方法详解
2016/05/10 Javascript
浅析jQuery 遍历函数,javascript中的each遍历
2016/05/25 Javascript
JavaScript常用判断写法大全(推荐)
2016/05/30 Javascript
JavaScript 闭包详细介绍
2016/09/28 Javascript
jQuery checkbox选中问题之prop与attr注意点分析
2016/11/15 Javascript
用JavaScript实现让浏览器停止载入页面的方法
2017/01/19 Javascript
JavaScript 数据类型详解
2017/03/13 Javascript
详解vuex commit保存数据技巧
2018/12/25 Javascript
一文了解Vue中的nextTick
2019/05/06 Javascript
vue父子组件通信的高级用法示例
2019/08/29 Javascript
JSONObject与JSONArray使用方法解析
2020/09/28 Javascript
[05:07]DOTA2英雄梦之声_第14期_暗影恶魔
2014/06/20 DOTA
[01:32:10]NAVI vs VG Supermajor 败者组 BO3 第一场 6.5
2018/06/06 DOTA
python实现简单socket程序在两台电脑之间传输消息的方法
2015/03/13 Python
python开发之str.format()用法实例分析
2016/02/22 Python
Python set常用操作函数集锦
2017/11/15 Python
Python实现桶排序与快速排序算法结合应用示例
2017/11/22 Python
python登录并爬取淘宝信息代码示例
2017/12/09 Python
Python 网络编程之TCP客户端/服务端功能示例【基于socket套接字】
2019/10/12 Python
pytorch的batch normalize使用详解
2020/01/15 Python
django教程如何自学
2020/07/31 Python
css3加js做一个简单的3D行星运转效果实例代码
2017/01/18 HTML / CSS
党的群众路线教育实践活动个人对照检查材料(公安)
2014/11/05 职场文书
2014小学教师年度考核工作总结
2014/12/03 职场文书
义诊活动总结
2015/02/04 职场文书
2015年项目工作总结
2015/04/29 职场文书
mysql sum(if())和count(if())的用法说明
2022/01/18 MySQL