celery 入门
认识
这里有几个概念,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(, )
- >>> add.delay(,)
- <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(, )
- >>> result.ready()
- True
- >>> result.get()
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)
参考:http://windrocblog.sinaapp.com/?p=1585
celery 入门的更多相关文章
- Celery入门指北
Celery入门指北 其实本文就是我看完Celery的官方文档指南的读书笔记.然后由于我的懒,只看完了那些入门指南,原文地址:First Steps with Celery,Next Steps,Us ...
- 分布式队列Celery入门
Celery 是一个简单.灵活且可靠的,处理大量消息的分布式系统,并且提供维护这样一个系统的必需工具.它是一个专注于实时处理的任务队列,同时也支持任务调度.Celery 是语言无关的,虽然它是用 Py ...
- celery入门
认识 这里有几个概念,task.worker.broker.顾名思义,task 就是老板交给你的各种任务,worker 就是你手下干活的人员. 那什么是 Broker 呢? 老板给你下发任务时,你需要 ...
- 分布式任务队列Celery入门与进阶
一.简介 Celery是由Python开发.简单.灵活.可靠的分布式任务队列,其本质是生产者消费者模型,生产者发送任务到消息队列,消费者负责处理任务.Celery侧重于实时操作,但对调度支持也很好,其 ...
- 异步任务神器 Celery-入门
一.Celery入门介绍 在程序的运行过程中,我们经常会碰到一些耗时耗资源的操作,为了避免它们阻塞主程序的运行,我们经常会采用多线程或异步任务.比如,在 Web 开发中,对新用户的注册,我们通常会给他 ...
- 初识Celery
本系列文章的开发环境: window + python2. + pycharm5 + celery3.1.25 + django1.9.4 在我们日常的开发工作中,经常会遇到这几种情况: 1.在web ...
- Celery异步调度框架(一)基本使用
介绍 之前部门开发一个项目我们需要实现一个定时任务用于收集每天DUBBO接口.域名以及TOMCAT(核心应用)的访问量,这个后面的逻辑就是使用定时任务去ES接口抓取数据存储在数据库中然后前台进行展示. ...
- Django中使用Celery
一.前言 Celery是一个基于python开发的分布式任务队列,如果不了解请阅读笔者上一篇博文Celery入门与进阶,而做python WEB开发最为流行的框架莫属Django,但是Django的请 ...
- 转 Celery 使用
http://www.mamicode.com/info-detail-1798782.html https://blog.csdn.net/lu1005287365/article/details/ ...
随机推荐
- Jquery&JS简单选项卡
结果,如图 为了明显,用绿色+红色 第一步:静态布局 先写html代码和css样式 要点一: ul li都为块级元素,可以用height,但是里面字体不居中,我们用line-height,即达到居中 ...
- 用MSoffice里的绘图工具
试过一些绘图表的工具,在xbeta推荐的替代visio一文中介绍的一些软件.之前用得最多的就是Dia,在linux下也有.现在才发现在微软的office下的绘图工具已经足够我使用了,不需要专业的图形符 ...
- ubuntu下用virtualbox安装windows虚拟机
按照这个教程: http://jingyan.baidu.com/article/eae07827856ac21fed54856f.html 安装. 会出现问题:"VT-x is disab ...
- CodeForces 577B 模和vecto
上一年的最后一次训练赛被卡了AK... 一开始天真的认为每个数字都进行取模 然后认为它是一个vol为取模后的数 val为0的01背包 去计算dp[m]能否被装满 只想到了其中的一点..简直天真 后来看 ...
- PHP fwrite() 函数与 file_put_contents() 函数的比较
两个 PHP 函数都可以把字符串保存到文件中,fwrite() 函数的格式是: int fwrite ( resource handle , string string [ , int length] ...
- js 获取checkbox选中项目
# //获取选中项 $('#submit').click(function () { var check_list = [] $("input[name='ck']:checked" ...
- 综合支撑【恶灵附身 Psycho Break】的世界观的概念艺术
综合支撑[恶灵附身 Psycho Break]的世界观的概念艺术 三上真司监督提出的,是对着重表现讲述内心恐怖的哪个世界观的创作和统一做了很大贡献的概念艺术. 这里以他经手的艺术为例,来看看稀少的恐 ...
- Java ArrayListSerialise
import java.io.*; import java.util.*; //ArrayListSerialise public class A { public static void main( ...
- 哈哈,好像swift 以后有可能用来开发安卓喔
好像swift 以后有可能用来开发安卓喔,哈哈
- java类加载过程
类(型)的生命周期--装载.连接.初始化.卸载 Java虚拟机通过装载.连接和初始化一个Java类型,使该类型可以被正在运行的Java程序所使用. 1. 装载 装载阶段包括三个基本动作: ...