转载请注明出处:点我

我的第一篇博客!嘿嘿!

在公司实习,接触到的第一个项目就用到了Celery,之前是完全没有接触过Celery这玩意,然后花了点时间仔细的研究了下怎么用。在学习过程中也遇到了些问题,所以把自己的学习过程记录下来,供他人参考下。

先说一下我的实验环境:两台ubuntu的机子,一台win7的机子,都安装好了必须的软件。用户名为atsgxxx的机子跑的是ubuntu的系统,Redis就运行在这个上面,另外一台ubuntu的机子的用户名是sclu084。

Celery

那么什么是Celery呢?

Celery是一个用Python开发的异步的分布式任务调度模块。

Celery本身不包含消息服务,使用第三方消息服务,也就是Broker,来传递任务,目前支持的有Rebbimq,Redis,数据库以及其他的一些比如Amazon SQS,Monogdb和IronMQ 

因为项目里面用的是Redis,所以这里以Redis作为Broker。

安装Celery

sudo apt-get install celery

使用Redis作为Broker的话,可以两者一块安装

sudo pip install -U celery[redis]

当然如果正式生产环境中,有可能redis服务器和Celery在不同的机器上面的话,就要两者单独安装

sudo apt-get install redis-server 这个命令可以安装redis,包括了redi-cli工具

第一个简单的例子

这个例子来自于Celery的官方文档。先看代码:

 from celery import Celery
app = Celery('tasks',broker="redis://127.0.0.1:6379/0") @app.task
def add(x,y):
return x + y

把代码保存为tasks.py文件(这个例子运行在atsgxxx这台机器上,上面运行了Redis,所以broker是127.0.0.1)。然后再terminal下启动worker。

celery -A tasks worker -l info

这个命令会启动一个worker来执行task。执行完这条命令后,不出意外的出现下面这个界面的话表示worker已经启动成功,正在等待执行任务。

然后启动另外一个终端,进入python工作环境,执行任务,如下图所示:

调用delay函数即可启动add这个任务,add函数的参数为4,4,这个函数的效果是发送一条消息到broker中去,这个消息包括要执行的函数已经执行函数的参数,还有一些其他信息,具体的可以看Celery的文档。

因为之前已经启动了一个worker,这个worker会等待broker中的消息,一旦收到消息就会立刻执行消息
启动了一个任务之后,可以看到之前启动的worker已经开始执行任务了。效果如下图所示:

从上图中可以看到,任务已经被执行成功。

Celery与分布式

既然Celery是一个分布式的任务调度模块,那么Celery是如何跟分布式挂上钩的呢?首先得明白什么是分布式。我的理解是所谓的分布式就是由多台分布在不同地方的计算机通过网络共同完成任务。在Celery里面,就可以是多台不同的计算机执行不同的任务或者是相同的任务。
如果要说Celery的分布式应用的话,我觉得就要提到Celery的消息路由机制,就要提一下AMQP协议。具体的可以查看AMQP的文档。简单地说就是可以有多个消息队列(Message Queue),不同的消息可以指定发送给不同的Message Queue,而这是通过Exchange来实现的。发送消息到Message Queue中时,可以指定routiing_key,Exchange通过routing_key来把消息路由(routes)到不同的Message Queue中去。具体的可以参考下这个网页,上面讲的很详细的了。

现在来看下代码:(代码实现的功能是在两台ubuntu上面启动worker,每个worker执行指定的Queue中的Task,然后在win7上面执行消息。同时演示了默认消息队列的使用。)

 from celery import Celery

 app = Celery()
app.config_from_object("celeryconfig") @app.task
def taskA(x,y):
return x + y @app.task
def taskB(x,y,z):
return x + y + z @app.task
def add(x,y):
return x + y

上面的tasks.py中,首先定义了一个Celery对象,然后用celeryconfig.py对celery对象进行设置,之后再分别定义了三个task,分别是taskA,taskB和add。接下来看一下celeryconfig.py文件

 from kombu import Exchange,Queue

 BROKER_URL = "redis://10.32.105.227:6379/0" CELERY_RESULT_BACKEND = "redis://10.32.105.227:6379/0"

 CELERY_QUEUES = (
     Queue("default",Exchange("default"),routing_key="default"),
     Queue("for_task_A",Exchange("for_task_A"),routing_key="task_a"),
     Queue("for_task_B",Exchange("for_task_B"),routing_key="task_a")
   ) CELERY_ROUTES = {
'tasks.taskA':{"queue":"for_task_A","routing_key":"task_a"},
'tasks.taskB":{"queue":"for_task_B","routing_key:"task_b"}
}

在celeryconfig.py文件中,首先设置了brokel以及result_backend,接下来定义了三个Message Queue,并且指明了Queue对应的Exchange(当使用Redis作为broker时,Exchange的名字必须和Queue的名字一样)以及routing_key的值。

现在现在其中一台ubuntu上面启动一个worker,这个worker只执行for_task_A队列中的消息,这是通过在启动worker是使用-Q Queue_Name参数指定的。

celery -A tasks worker -l info -n worker.%h -Q for_task_A

其中-n参数表示这个worker的name,-Q参数指定了这个worker执行for_task_A队列中的消息。执行结果如下图所示:

上面的执行结果表明名字为worker.atsgxxx的任务已经启动,等待执行for_task_A中的任务。

然后再win7上面执行taskA任务。在win7上,进入CMD,切换当前目录到代码坐在的工程下,启动python,执行下面代码启动taskA:

from tasks import *

task_A_re = taskA.delay(100,200)

执行完上面的代码之后,task_A消息会被立即发送到for_task_A队列中去。此时已经启动的worker.atsgxxx 会立即执行taskA任务。效果如下图所示:

可以看到taskA已经被worker.atsgxxx执行成功.

然后再win7上面查看taskA的执行状态:

也显示taskA已经成功被执行了。

重复上面的过程,在另外一台机器上启动一个worker专门执行for_task_B中的任务,在win7上执行taskB任务。整个过程及结果如下面的图所示:

在上面的tasks.py文件中还定义了add任务,但是在celeryconfig.py文件中没有指定这个任务route到那个Queue中去执行,此时执行add任务的时候,add会route到Celery默认的名字叫做celery的队列中去。

下面现在wind7上面执行add任务,然后再另外一个终端上面启动一个worker执行名字为celery的队列中的消息(这个名字叫做celery的Queue不是我们定义的,是Celery默认的)。结果如下图所示:

此时可以看到add任务的状态是PENDING,表示还没有被执行,因为这个消息没有在celeryconfig.py文件中指定应该route到哪一个Queue中,所以会被发送到默认的名字为celery的Queue中,但是我们还没有启动worker执行celery中的任务。接下来我们在启动一个worker执行celery队列中的任务。

celery -A tasks worker -l info -n worker.%h -Q celery

然后再查看add的状态,会发现状态由PENDING变成了SUCCESS。效果如下图所示:

Celery与定时任务

在celery中执行定时任务非常简单,只需要设置celery对象的CELERYBEAT_SCHEDULE属性即可。

下面我们接着上面的代码,在celeryconfig.py中添加CELERYBEAT_SCHEDULE变量:

 CELERY_TIMEZONE = 'UTC'
CELERYBEAT_SCHEDULE = {
'taskA_schedule' : {
'task':'tasks.taskA',
'schedule':20,
'args':(5,6)
},
'taskB_scheduler' : {
'task':"tasks.taskB",
"schedule":200,
"args":(10,20,30)
},
'add_schedule': {
"task":"tasks.add",
"schedule":10,
"args":(1,2)
}
}

其中定义了3个定时任务,即每隔20s执行taskA任务,参数为(5,6),每隔200s执行taskB任务,参数为(10,20,30),每隔10s执行add任务,参数为(1,2).通过下列命令启动一个定时任务:

celery -A tasks beat

使用beat参数即可启动定时任务。

下面分别在三台机器上面启动三个worker分别执行for_task_A,for_task_B和celery这三个Queue中的任务。启动之后,再在其中一台机器上面启动定时任务。结果如下图所示(第一张为启动定时任务一段时间后的截图):

可以看到一旦scheduler启动起来,就会按照CELERYBEAT_SCHEDULE指定的时间执行指定的任务。然后已经启动的worker已接受到一消息就会执行任务,如下图所示:

Celery学习笔记的更多相关文章

  1. celery 学习笔记 01-介绍

    celery 学习笔记 01-介绍 celery 是 python 中的常用的任务队列框架,经常用于异步调用.后台任务等工作.celery 本身以 python 写,但协议可在不同的语言中实现,其它语 ...

  2. celery学习笔记1

    生产者消费者模式 在实际的软件开发过程中,经常会碰到如下场景:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类.函数.线程.进程等).产生数据的模块,就形象地称为生产 ...

  3. celery学习笔记2

    1.定义: Celery是一个异步的任务队列(也叫做分布式任务队列) 2.工作结构 Celery分为3个部分 (1)worker部分负责任务的处理,即工作进程(我的理解工作进程就是你写的python代 ...

  4. Swift学习笔记一

    最近计划把Swift语言系统学习一下,然后将MagViewer用这种新语言重构一次,并且优化一下,这里记录一下Swift的学习笔记. Swift和Objective-C相比,在语法和书写形式上做了很多 ...

  5. Knockout.js快速学习笔记

    原创纯手写快速学习笔记(对官方文档的二手理解),更推荐有时间的话读官方文档 框架简介(Knockout版本:3.4.1 ) Knockout(以下简称KO)是一个MVVM(Model-View-Vie ...

  6. 【目录】Python学习笔记

    目录:Python学习笔记 目标:坚持每天学习,每周一篇博文 1. Python学习笔记 - day1 - 概述及安装 2.Python学习笔记 - day2 - PyCharm的基本使用 3.Pyt ...

  7. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  8. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  9. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

随机推荐

  1. 五种开源协议的比较(BSD,Apache,GPL,LGPL,MIT)(整理)

    BSD开源协议(original  BSD license.FreeBSD  license.Original  BSD license) BSD开源协议是一个给于使用者很大自由的协议.基本上使用者可 ...

  2. hdu 5253 最小生成树

    赤裸裸最小生成树,没啥说的,我用kruskal过的 /* * Author : ben */ #include <cstdio> #include <cstdlib> #inc ...

  3. 配置Texmaker中文支持

    在Ubuntu 12.04 LTS下安装Texmaker后,如需要支持中文环境,需要安装CJK包. 终端(Ctrl+Alt+T(Terminal))下输入命令切换到超级管理员: sudo -i 安装包 ...

  4. Python中的并发编程

    简介 我们将一个正在运行的程序称为进程.每个进程都有它自己的系统状态,包含内存状态.打开文件列表.追踪指令执行情况的程序指针以及一个保存局部变量的调用栈.通常情况下,一个进程依照一个单序列控制流顺序执 ...

  5. static用法总结

    C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static.前者应用于普通变量和函数,不涉及类:后者主要说明static在类中的作用. 一.面向过程设计中的st ...

  6. DouNet学习_代码生成器

    string conn = "Data Source={0};Initial Catalog={1};User Id={2};Password={3}"; //点击链接 priva ...

  7. 刚刚大学毕业,自己搭网站遇到的问题 一:tomcat中同时部署两个项目的问题

    最近直接把两个项目打成war包在tomcat下发布,出现了很多莫名奇妙的问题,就是不能发布成功,只能有一个项目能成功,在网上查了很多方法,以为是两个项目中jar包出现冲突,也按照网上的方法把两个项目中 ...

  8. leetcode@ [146] LRU Cache (TreeMap)

    https://leetcode.com/problems/lru-cache/ Design and implement a data structure for Least Recently Us ...

  9. cc.Sprite

    Classcc.Sprite Defined in: CCSprite.js Extends cc.NodeRGBA Class Summary Constructor Attributes Cons ...

  10. java Study 基础 1

    1.myEclipse 生成get.set,source>Generate getter and setter 2.Web servlet.HttpServlet.HttpServletRequ ...