在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获取运行目录与当前脚本目录的方法
Jun 01 Python
Swift中的协议(protocol)学习教程
Jul 08 Python
Python字典实现简单的三级菜单(实例讲解)
Jul 31 Python
Python3多线程操作简单示例
May 22 Python
Pandas 合并多个Dataframe(merge,concat)的方法
Jun 08 Python
Django中日期处理注意事项与自定义时间格式转换详解
Aug 06 Python
详解Python正则表达式re模块
Mar 19 Python
python多任务之协程的使用详解
Aug 26 Python
Python使用Matlab命令过程解析
Jun 04 Python
Python Socket多线程并发原理及实现
Dec 11 Python
Python pandas之求和运算和非空值个数统计
Aug 07 Python
python通过新建环境安装tfx的问题
May 20 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+MySql编写聊天室
2006/10/09 PHP
URL Rewrite的设置方法
2007/01/02 PHP
php文件夹的创建与删除方法
2015/01/24 PHP
PHP的Socket网络编程入门指引
2015/08/11 PHP
PHP注释语法规范与命名规范详解篇
2018/01/21 PHP
JavaScript前端图片加载管理器imagepool使用详解
2014/12/29 Javascript
jQuery获得子元素个数的方法
2015/04/14 Javascript
JavaScript实现点击文字切换登录窗口的方法
2015/05/11 Javascript
WordPress中鼠标悬停显示和隐藏评论及引用按钮的实现
2016/01/12 Javascript
在ASP.NET MVC项目中使用RequireJS库的用法示例
2016/02/15 Javascript
js中利用cookie实现记住密码功能
2020/08/20 Javascript
jquery实现tab选项卡切换效果(悬停、下方横线动画位移)
2017/05/05 jQuery
JavaScript设计模式之模板方法模式原理与用法示例
2018/08/07 Javascript
说说Vue.js中的functional函数化组件的使用
2019/02/12 Javascript
Vue 解决路由过渡动画抖动问题(实例详解)
2020/01/05 Javascript
vue通过v-html指令渲染的富文本无法修改样式的解决方案
2020/05/20 Javascript
[19:24]DOTA2客户端使用指南 一分钟快速设置轻松超神
2013/09/24 DOTA
python实现跨文件全局变量的方法
2014/07/07 Python
Python安装Imaging报错:The _imaging C module is not installed问题解决方法
2014/08/22 Python
详尽讲述用Python的Django框架测试驱动开发的教程
2015/04/22 Python
Python语言实现百度语音识别API的使用实例
2017/12/13 Python
python/sympy求解矩阵方程的方法
2018/11/08 Python
python实现把二维列表变为一维列表的方法分析
2019/10/08 Python
Python发送邮件实现基础解析
2020/08/14 Python
python实现自动打卡的示例代码
2020/10/10 Python
Jack Rogers官网:美国经典的女性鞋靴品牌
2019/09/04 全球购物
维多利亚的秘密阿联酋官网:Victoria’s Secret阿联酋
2019/12/07 全球购物
将一个数的从第5位开始的7个数取出,其余位置0
2016/05/26 面试题
介绍一下Prototype的$()函数,$F()函数,$A()函数都是什么作用?
2014/03/05 面试题
信访工作者先进事迹
2014/01/17 职场文书
工厂门卫的岗位职责
2014/07/27 职场文书
房屋授权委托书范本
2014/10/07 职场文书
2014年电信员工工作总结
2014/12/19 职场文书
2015年行政助理工作总结
2015/04/30 职场文书
Python爬虫爬取全球疫情数据并存储到mysql数据库的步骤
2021/03/29 Python
OpenCV绘制圆端矩形的示例代码
2021/08/30 Python