认识

这里有几个概念,task、worker、broker。
顾名思义,task 就是老板交给你的各种任务,worker 就是你手下干活的人员。

那什么是 Broker 呢?

老板给你下发任务时,你需要 把它记下来, 这个它 可以是你随身携带的本子,也可以是 电脑里地记事本或者excel,或者是你的 任何时间管理工具。

Broker  则是 Celery 记录task的地方。
作为一个任务管理者的你,将老板(前端程序)发给你的 安排的工作(Task) 记录到你的本子(Broker)里。接下来,你就安排你手下的IT程序猿们(Worker),都到你的本子(Broker)里来取走工作(Task)

1. broker为rabbitmq

#tasks.py

from celery import Celery

app = Celery('tasks', broker='amqp://admin:admin@localhost:5672')

@app.task
def add(x, y):
return x + y

启动

celery -A tasks worker --loglevel=info

运行

>>> from tasks import add
>>> add(1, 3)
4
>>> add.delay(1,3)
<AsyncResult: 07614cef-f314-4c7b-a33f-92c080cadb83>
>>>

:delay是使用异步的方式,会压入到消息队列。否则,不会使用消息队列。

文件名为tasks.py,则其中代码app = Celery('tasks', broker=),Celery第一个参数为工程名,启动时也是celery -A tasks worker --loglevel=info

对比

:投入到指定的队列用:add.delay(1, 3, queue='queue_add1')

test_2.py

from celery import Celery

app = Celery('proj', broker='amqp://admin:admin@localhost:5672', include='test_2')

@app.task
def add(x, y):
return x + y

2. 以python+文件名的方式启动

例1:

#test.py

from celery import Celery
import time
app = Celery('test', backend='amqp', broker='amqp://admin:admin@localhost:5672') @app.task
def add(x, y):
print "------>"
time.sleep(5)
print "<--------------"
return x + y if __name__ == "__main__":
app.start()

启动

python test.py worker 

celery默认启动的worker数为内核个数,如果指定启动个数,用参数-c,例

python test.py worker -c 2

例2:

#test.py

from celery import Celery
import time
app = Celery('test', backend='amqp', broker='amqp://admin:admin@localhost:5672') @app.task
def add(x, y):
print "------>"
time.sleep(2)
print "<--------------"
return x + y if __name__ == "__main__":
app.start()

#eg.py

from test import *
import time rev = []
for i in range(3):
rev.append(add.delay(1,3)) print "len rev:", len(rev)
while 1:
tag = 1
for key in rev:
if not key.ready():
tag = 0
time.sleep(1)
print "sleep 1"
if tag:
break
print "_____________________>"

3. broker为redis

#test_redis.py

from celery import Celery
import time
#app = Celery('test_redis', backend='amqp', broker='redis://100.69.201.116:7000')
app = Celery('test_redis', backend='redis', broker='redis://100.69.201.116:7000') @app.task
def add(x, y):
print "------>"
time.sleep(5)
print "<--------------"
return x + y if __name__ == "__main__":
app.start()

启动

python test_redis.py worker -c 2

测试

from celery import group
from test_redis import *
g = group(add.s(2, 3)).apply_async()
g = group(add.s(2, 3)).apply_async()
g = group(add.s(2, 3)).apply_async()
g = group(add.s(2, 3)).apply_async()
g = group(add.s(2, 3)).apply_async()
for ret in g.get():
print ret
print "end-----------------------------------"

结果

5
end-----------------------------------

4. 两个队列(redis)

#test_redis.py

from celery import Celery
import time
#app = Celery('test_redis', backend='amqp', broker='redis://100.69.201.116:7000')
app = Celery('test_redis', backend='redis', broker='redis://100.69.201.116:7000') @app.task
def add(x, y):
print "------>"
time.sleep(5)
print "<--------------"
return x + y if __name__ == "__main__":
app.start()

#test_redis_2.py

from celery import Celery
import time
#app = Celery('test_redis', backend='amqp', broker='redis://100.69.201.116:7000')
app = Celery('test_redis_2', backend='redis', broker='redis://100.69.201.116:7001') @app.task
def add_2(x, y):
print "=======>"
time.sleep(5)
print "<================="
return x + y if __name__ == "__main__":
app.start()

测试

from celery import group
from test_redis import *
from test_redis_2 import *
ll = [(1,2), (3,4), (5,6)]
g = group(add.s(key[0], key[1]) for key in ll).apply_async()
for ret in g.get():
print ret
print "end redis_1 -----------------------------------" ll = [(1,2), (3,4), (5,6)]
g = group(add_2.s(key[0], key[1]) for key in ll).apply_async()
for ret in g.get():
print ":", ret
print "end redis_2 -----------------------------------"

结果

3
7
11
end redis_1 -----------------------------------
: 3
: 7
: 11
end redis_2 -----------------------------------

5. 两个队列(同一个rabbitmq)

注释:需要提前设置下队列

##例1

#test.py

from celery import Celery
import time
app = Celery('test', backend='amqp', broker='amqp://admin:admin@localhost:5672//') @app.task
def add(x, y):
print "------>"
time.sleep(5)
print "<--------------"
return x + y if __name__ == "__main__":
app.start()

#test_2.py

from celery import Celery
import time
app = Celery('test_2', backend='amqp', broker='amqp://admin:admin@localhost:5672//hwzh') @app.task
def add_2(x, y):
print "=====>"
time.sleep(5)
print "<=========="
return x + y if __name__ == "__main__":
app.start()

测试

from celery import group
from test import *
from test_2 import * ll = [(1,2), (3,4), (7,8)]
g = group(add.s(key[0], key[1]) for key in ll).apply_async()
for ret in g.get():
print ret ll = [(1,2), (3,4), (7,8)]
g = group(add_2.s(key[0], key[1]) for key in ll).apply_async()
for ret in g.get():
print ret

结果

3
7
15
3
7
15

##例2

#test.py

from celery import Celery
import time
app = Celery('test', backend='amqp', broker='amqp://admin:admin@localhost:5672//mq4') @app.task
def add(x, y):
print "------>"
time.sleep(2)
print "<--------------"
return x + y @app.task
def sum(x, y):
print "------>"
time.sleep(2)
print "<--------------"
return x + y if __name__ == "__main__":
app.start()

#eg2.py

from test import *
import time rev = []
for i in range(3):
rev.append(add.delay(1,3)) for i in range(3):
rev.append(sum.delay(1,3)) print "len rev:", len(rev)
while 1:
tag = 1
for key in rev:
if not key.ready():
tag = 0
time.sleep(1)
print "sleep 1"
if tag:
break
print "_____________________>"

6. 保存结果

from celery import Celery

app = Celery('tasks', backend='amqp', broker='amqp://admin:admin@localhost')

@app.task
def add(x, y):
return x + y

启动

celery -A tasks_1 worker --loglevel=info

与前例不同:

- ** ---------- [config]
- ** ---------- .> app: tasks:0x7f8057931810
- ** ---------- .> transport: amqp://admin:**@localhost:5672//
- ** ---------- .> results: amqp

运行

>>> from tasks_1 import add
>>> result = add.delay(1, 3)
>>> result.ready()
True
>>> result.get()
4

7. 多个队列

from celery import Celery
from kombu import Exchange, Queue
BROKER_URL = 'amqp://admin:admin@localhost//'
app = Celery('tasks', backend='amqp',broker=BROKER_URL)
app.conf.update(
CELERY_ROUTES={
"add1":{"queue":"queue_add1"},
"add2":{"queue":"queue_add2"},
"add3":{"queue":"queue_add3"},
"add4":{"queue":"queue_add4"},
},
)
@app.task
def add1(x, y):
return x + y @app.task
def add2(x, y):
return x + y @app.task
def add3(x, y):
return x + y @app.task
def add4(x, y):
return x + y

8. 消息路由

文件:tasks.py

from celery import Celery, platforms
import time
import os app = Celery('proj', broker='amqp://admin:admin@ip:5672',
include=['tasks']
)
app.conf.update(
CELERY_ROUTES={
'tasks.fun_1': {
'queue': "q_1"
},
'tasks.fun_2': {
'queue': "q_2"
}
}
)
platforms.C_FORCE_ROOT = True @app.task
def fun_1(n):
print "(((((((((((((((func_1", n
return 1 @app.task
def fun_2(n):
print n, ")))))))))))))))"
return 2 if __name__ == "__main__":
app.start()

启动

python tasks.py worker -c 2 -Q q_1
python tasks.py worker -c 2 -Q q_2

两个消息队列:q_1, q_2,调用示例

>>> from tasks import *
>>> fun_1(1)
(((((((((((((((func_1 1
1
>>> fun_1.delay(1)
<AsyncResult: 528a2ad1-bc16-4bdc-beff-cd166fe3e885>
>>> fun_2.delay(2)
<AsyncResult: ee5881eb-b384-4a39-ba00-08aa8ee53504>

9. woker内启多进程

#tasks.py

from celery import Celery
import time
import multiprocessing as mp app = Celery('proj', broker='amqp://admin:admin@ip:5672', include="tasks") def test_func(i):
print "beg...:", i
time.sleep(5)
print "....end:", i
return i * 5 @app.task
def fun_1(n):
curr_proc = mp.current_process()
curr_proc.daemon = False
p = mp.Pool(mp.cpu_count())
curr_proc.daemon = True
for i in range(n):
p.apply_async(test_func, args=(i,))
p.close()
p.join()
return 1 if __name__ == "__main__":
app.start()

说明

直接启动多进程是肯定不可以的,因为是守候进程(curr_proc.daemon=True),所以启多进程之前主动设置为非守候进程:curr_proc.daemon=False,启动了以后再设为守候进程

#tasks_callback.py

from celery import Celery
import time
import multiprocessing as mp app = Celery('proj', broker='amqp://admin:admin@ip:5672', include="tasks_callback")
rev = []
def test_func(i):
print "beg...:", i
time.sleep(5)
print "....end:", i
return i * 5 def callback_log(rev_val):
rev.append(rev_val) @app.task
def fun_1(n):
print "before rev:", rev
curr_proc = mp.current_process()
curr_proc.daemon = False
p = mp.Pool(mp.cpu_count())
curr_proc.daemon = True
for i in range(n):
p.apply_async(test_func, args=(i,), callback=callback_log)
p.close()
p.join()
print "after rev:", rev
return 1 if __name__ == "__main__":
app.start()

10. 常用参数配置

1. CELERYD_PREFETCH_MULTIPLIER

同时预取得消息个数,比如如果CELERYD_PREFETCH_MULTIPLIER=2,那么如果现在对于1个worker,有一个状态是STARTED, 那么可以有2个处于RECEVED状态(如果有的话),这样就避免了如果消息很多全部分下取,后起来的worker领不到消息的尴尬。

参考代码

from celery import Celery, platforms
import time
import os app = Celery('proj', broker='amqp://admin:admin@localhost:5672',
include=['tasks']
)
app.conf.update(
CELERYD_PREFETCH_MULTIPLIER=2,
CELERY_ROUTES={
'tasks.fun_1': {
'queue': "q_1"
},
'tasks.fun_2': {
'queue': "q_2"
}
}
)
platforms.C_FORCE_ROOT = True @app.task
def fun_1(n):
print "(((((((((((((((func_1", n
time.sleep(20)
return 1 @app.task
def fun_2(n):
print n, ")))))))))))))))"
return 2

调用

>>> from tasks import *
>>> fun_1.delay(3)
<AsyncResult: 609f2216-6785-409e-9f6f-85ae3fcce084>
>>> fun_1.delay(3)
<AsyncResult: 0230b8bd-b237-40ef-bc73-88929f8f8290>
>>> fun_1.delay(3)
<AsyncResult: 8fce172a-93c9-41f8-8c08-377a4363389c>
>>> fun_1.delay(3)

celery 实例进阶的更多相关文章

  1. Laravel5.0学习--02 实例进阶

    本文以laravel5.0.22为例. 本节以新建一个简单的博客作为实例. 准备工作 数据库配置 .env文件(也可以直接修改config/database.php) DB_HOST=localhos ...

  2. 分布式任务队列Celery入门与进阶

    一.简介 Celery是由Python开发.简单.灵活.可靠的分布式任务队列,其本质是生产者消费者模型,生产者发送任务到消息队列,消费者负责处理任务.Celery侧重于实时操作,但对调度支持也很好,其 ...

  3. Celery(三)实例Application

    Celery必须实例化后才可以使用,实例称之为application或者简称app.实例是线程安全的,多个Celery实例(不同的配置.部件和任务)都可以在一个进程空间中运行. 创建一个最简单的app ...

  4. Celery初识及简单实例

    Celery是一个“自带电池”的任务队列.易于使用,可以轻易入门,它遵照最佳实践设计,使产品可以扩展,或与其他语言集成,并且它自带了在生产环境中运行这样一个系统所需的工具和支持.本文介绍基础部分: 选 ...

  5. celery 基础教程(二):简单实例

    前言 使用celery包含三个方面:1. 定义任务函数.2. 运行celery服务.3. 客户应用程序的调用. 实例一: #1. 定义任务函数 创建一个文件 tasks.py输入下列代码: from ...

  6. celery 框架

    转自:http://www.cnblogs.com/forward-wang/p/5970806.html 生产者消费者模式 在实际的软件开发过程中,经常会碰到如下场景:某个模块负责产生数据,这些数据 ...

  7. celery 异步任务小记

    这里有一篇写的不错的:http://www.jianshu.com/p/1840035cb510 自己的"格式化"后的内容备忘下: 我们总在说c10k的问题, 也做了不少优化, 然 ...

  8. Celery 框架学习笔记

    在学习Celery之前,我先简单的去了解了一下什么是生产者消费者模式. 生产者消费者模式 在实际的软件开发过程中,经常会碰到如下场景:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是 ...

  9. Celery,Tornado,Supervisor构建和谐的分布式系统

    Celery 分布式的任务队列 与rabbitmq消息队列的区别与联系: rabbitmq 调度的是消息,而Celery调度的是任务. Celery调度任务时,需要传递参数信息,传输载体可以选择rab ...

随机推荐

  1. Linux按照CPU、内存、磁盘IO、网络性能监测【转载】

    本文转载地址:https://my.oschina.net/chape/blog/159640 系统优化是一项复杂.繁琐.长期的工作,优化前需要监测.采集.测试.评估,优化后也需要测试.采集.评估.监 ...

  2. k8s实战之数据卷(volume)

    一.概述 数据卷用于实现容器持久化数据,k8s对于数据卷重新定义,提供了丰富强大的功能:数据卷分为三类: 本地数据卷,网络数据卷和信息数据卷 二.

  3. 【jsp】详解JSP表达式语言(EL)

    一.JSP EL语言定义 E L(Expression Language)  目的:为了使JSP写起来更加简单. 表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 ...

  4. Postgresql 正则表达式

    在postgresql中使用正则表达式时需要使用关键字“~”,以表示该关键字之前的内容需匹配之后的正则表达式,若匹配规则不需要区分大小写,可以使用组合关键字“~*”: 相反,若需要查询不匹配这则表达式 ...

  5. 解决虚拟机vmware虚拟机安装64位系统“此主机支持 Intel VT-x,但 Intel VT-x 处于禁用状态”的问题

    前言 虚拟机使用的是VMware Workstation,并且首次在虚拟机体验64 位系统.在新建好虚拟机,运行时候就出现了VMware Workstation 的提醒:此主机支持 Intel VT- ...

  6. Xtrabackup备份、还原、恢复Mysql操作大全

    环境:CentOS 6.7  + Mysql 5.7.19 + Xtraback 2.4.8 innobackupex常用参数: --user=USER 指定备份用户,不指定的话为当前系统用户 --p ...

  7. sqlite 判断表中是否包含 某个字段

    数据库 都有一个 根表..(我的理解) 也就是 你创建了一个数据库 里面就带有 一个表 sqlite_master 字段有 type , name  , tbl_name , rootpage ,sq ...

  8. js获取checkbox复选框获取选中的选项

    js获取checkbox复选框获取选中的选项 分享下javascript获取checkbox 复选框获取选中的选项的方法. 有关javascript 获取checkbox复选框的实例数不胜数.js实现 ...

  9. 【Unity】3.0 第3章 创建和导入3D模型

    分类:Unity.C#.VS2015 创建日期:2016-04-02 一.简介 利用Unity内置的基本模型和工具,不需要借助任何其他的三维建模软件,就可以直接创建出各种3D模型,这是这一章我们首先学 ...

  10. mySql索引优化分析

    MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字 ...