认识

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

那什么是 Broker 呢?

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

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

1. broker为rabbitmq

#tasks.py

  1. from celery import Celery
  2.  
  3. app = Celery('tasks', broker='amqp://admin:admin@localhost:5672')
  4.  
  5. @app.task
  6. def add(x, y):
  7. return x + y

启动

  1. celery -A tasks worker --loglevel=info

运行

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

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

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

对比

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

test_2.py

  1. from celery import Celery
  2.  
  3. app = Celery('proj', broker='amqp://admin:admin@localhost:5672' include='test_2')
  4.  
  5. @app.task
  6. def add(x, y):
  7. return x + y

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

例1:

#test.py

  1. from celery import Celery
  2. import time
  3. app = Celery('test', backend='amqp', broker='amqp://admin:admin@localhost:5672')
  4.  
  5. @app.task
  6. def add(x, y):
  7. print "------>"
  8. time.sleep(5)
  9. print "<--------------"
  10. return x + y
  11.  
  12. if __name__ == "__main__":
  13. app.start()

启动

  1. python test.py worker

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

  1. python test.py worker -c 2

例2:

#test.py

  1. from celery import Celery
  2. import time
  3. app = Celery('test', backend='amqp', broker='amqp://admin:admin@localhost:5672')
  4.  
  5. @app.task
  6. def add(x, y):
  7. print "------>"
  8. time.sleep(2)
  9. print "<--------------"
  10. return x + y
  11.  
  12. if __name__ == "__main__":
  13. app.start()

#eg.py

  1. from test import *
  2. import time
  3.  
  4. rev = []
  5. for i in range(3):
  6. rev.append(add.delay(1,3))
  7.  
  8. print "len rev:", len(rev)
  9. while 1:
  10. tag = 1
  11. for key in rev:
  12. if not key.ready():
  13. tag = 0
  14. time.sleep(1)
  15. print "sleep 1"
  16. if tag:
  17. break
  18. print "_____________________>"

3. broker为redis

#test_redis.py

  1. from celery import Celery
  2. import time
  3. #app = Celery('test_redis', backend='amqp', broker='redis://100.69.201.116:7000')
  4. app = Celery('test_redis', backend='redis', broker='redis://100.69.201.116:7000')
  5.  
  6. @app.task
  7. def add(x, y):
  8. print "------>"
  9. time.sleep(5)
  10. print "<--------------"
  11. return x + y
  12.  
  13. if __name__ == "__main__":
  14. app.start()

启动

  1. python test_redis.py worker -c 2

测试

  1. from celery import group
  2. from test_redis import *
  3. g = group(add.s(2, 3)).apply_async()
  4. g = group(add.s(2, 3)).apply_async()
  5. g = group(add.s(2, 3)).apply_async()
  6. g = group(add.s(2, 3)).apply_async()
  7. g = group(add.s(2, 3)).apply_async()
  8. for ret in g.get():
  9. print ret
  10. print "end-----------------------------------"

结果

  1. 5
  2. end-----------------------------------

4. 两个队列(redis)

#test_redis.py

  1. from celery import Celery
  2. import time
  3. #app = Celery('test_redis', backend='amqp', broker='redis://100.69.201.116:7000')
  4. app = Celery('test_redis', backend='redis', broker='redis://100.69.201.116:7000')
  5.  
  6. @app.task
  7. def add(x, y):
  8. print "------>"
  9. time.sleep(5)
  10. print "<--------------"
  11. return x + y
  12.  
  13. if __name__ == "__main__":
  14. app.start()

#test_redis_2.py

  1. from celery import Celery
  2. import time
  3. #app = Celery('test_redis', backend='amqp', broker='redis://100.69.201.116:7000')
  4. app = Celery('test_redis_2', backend='redis', broker='redis://100.69.201.116:7001')
  5.  
  6. @app.task
  7. def add_2(x, y):
  8. print "=======>"
  9. time.sleep(5)
  10. print "<================="
  11. return x + y
  12.  
  13. if __name__ == "__main__":
  14. app.start()

测试

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

结果

  1. 3
  2. 7
  3. 11
  4. end redis_1 -----------------------------------
  5. : 3
  6. : 7
  7. : 11
  8. end redis_2 -----------------------------------

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

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

##例1

#test.py

  1. from celery import Celery
  2. import time
  3. app = Celery('test', backend='amqp', broker='amqp://admin:admin@localhost:5672//')
  4.  
  5. @app.task
  6. def add(x, y):
  7. print "------>"
  8. time.sleep(5)
  9. print "<--------------"
  10. return x + y
  11.  
  12. if __name__ == "__main__":
  13. app.start()

#test_2.py

  1. from celery import Celery
  2. import time
  3. app = Celery('test_2', backend='amqp', broker='amqp://admin:admin@localhost:5672//hwzh')
  4.  
  5. @app.task
  6. def add_2(x, y):
  7. print "=====>"
  8. time.sleep(5)
  9. print "<=========="
  10. return x + y
  11.  
  12. if __name__ == "__main__":
  13. app.start()

测试

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

结果

  1. 3
  2. 7
  3. 15
  4. 3
  5. 7
  6. 15

##例2

#test.py

  1. from celery import Celery
  2. import time
  3. app = Celery('test', backend='amqp', broker='amqp://admin:admin@localhost:5672//mq4')
  4.  
  5. @app.task
  6. def add(x, y):
  7. print "------>"
  8. time.sleep(2)
  9. print "<--------------"
  10. return x + y
  11.  
  12. @app.task
  13. def sum(x, y):
  14. print "------>"
  15. time.sleep(2)
  16. print "<--------------"
  17. return x + y
  18.  
  19. if __name__ == "__main__":
  20. app.start()

#eg2.py

  1. from test import *
  2. import time
  3.  
  4. rev = []
  5. for i in range(3):
  6. rev.append(add.delay(1,3))
  7.  
  8. for i in range(3):
  9. rev.append(sum.delay(1,3))
  10.  
  11. print "len rev:", len(rev)
  12. while 1:
  13. tag = 1
  14. for key in rev:
  15. if not key.ready():
  16. tag = 0
  17. time.sleep(1)
  18. print "sleep 1"
  19. if tag:
  20. break
  21. print "_____________________>"

6. 保存结果

  1. from celery import Celery
  2.  
  3. app = Celery('tasks', backend='amqp', broker='amqp://admin:admin@localhost')
  4.  
  5. @app.task
  6. def add(x, y):
  7. return x + y

启动

  1. celery -A tasks_1 worker --loglevel=info

与前例不同:

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

运行

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

7. 多个队列

  1. from celery import Celery
  2. from kombu import Exchange, Queue
  3. BROKER_URL = 'amqp://admin:admin@localhost//'
  4. app = Celery('tasks', backend='amqp',broker=BROKER_URL)
  5. app.conf.update(
  6. CELERY_ROUTES={
  7. "add1":{"queue":"queue_add1"},
  8. "add2":{"queue":"queue_add2"},
  9. "add3":{"queue":"queue_add3"},
  10. "add4":{"queue":"queue_add4"},
  11. },
  12. )
  13. @app.task
  14. def add1(x, y):
  15. return x + y
  16.  
  17. @app.task
  18. def add2(x, y):
  19. return x + y
  20.  
  21. @app.task
  22. def add3(x, y):
  23. return x + y
  24.  
  25. @app.task
  26. def add4(x, y):
  27. return x + y

8. 消息路由

文件:tasks.py

  1. from celery import Celery, platforms
  2. import time
  3. import os
  4.  
  5. app = Celery('proj', broker='amqp://admin:admin@ip:5672',
  6. include=['tasks']
  7. )
  8. app.conf.update(
  9. CELERY_ROUTES={
  10. 'tasks.fun_1': {
  11. 'queue': "q_1"
  12. },
  13. 'tasks.fun_2': {
  14. 'queue': "q_2"
  15. }
  16. }
  17. )
  18. platforms.C_FORCE_ROOT = True
  19.  
  20. @app.task
  21. def fun_1(n):
  22. print "(((((((((((((((func_1", n
  23. return 1
  24.  
  25. @app.task
  26. def fun_2(n):
  27. print n, ")))))))))))))))"
  28. return 2
  29.  
  30. if __name__ == "__main__":
  31. app.start()

启动

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

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

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

9. woker内启多进程

#tasks.py

  1. from celery import Celery
  2. import time
  3. import multiprocessing as mp
  4.  
  5. app = Celery('proj', broker='amqp://admin:admin@ip:5672', include="tasks")
  6.  
  7. def test_func(i):
  8. print "beg...:", i
  9. time.sleep(5)
  10. print "....end:", i
  11. return i * 5
  12.  
  13. @app.task
  14. def fun_1(n):
  15. curr_proc = mp.current_process()
  16. curr_proc.daemon = False
  17. p = mp.Pool(mp.cpu_count())
  18. curr_proc.daemon = True
  19. for i in range(n):
  20. p.apply_async(test_func, args=(i,))
  21. p.close()
  22. p.join()
  23. return 1
  24.  
  25. if __name__ == "__main__":
  26. app.start()

说明

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

#tasks_callback.py

  1. from celery import Celery
  2. import time
  3. import multiprocessing as mp
  4.  
  5. app = Celery('proj', broker='amqp://admin:admin@ip:5672', include="tasks_callback")
  6. rev = []
  7. def test_func(i):
  8. print "beg...:", i
  9. time.sleep(5)
  10. print "....end:", i
  11. return i * 5
  12.  
  13. def callback_log(rev_val):
  14. rev.append(rev_val)
  15.  
  16. @app.task
  17. def fun_1(n):
  18. print "before rev:", rev
  19. curr_proc = mp.current_process()
  20. curr_proc.daemon = False
  21. p = mp.Pool(mp.cpu_count())
  22. curr_proc.daemon = True
  23. for i in range(n):
  24. p.apply_async(test_func, args=(i,), callback=callback_log)
  25. p.close()
  26. p.join()
  27. print "after rev:", rev
  28. return 1
  29.  
  30. if __name__ == "__main__":
  31. app.start()

10. 常用参数配置

1. CELERYD_PREFETCH_MULTIPLIER

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

参考代码

  1. from celery import Celery, platforms
  2. import time
  3. import os
  4.  
  5. app = Celery('proj', broker='amqp://admin:admin@localhost:5672',
  6. include=['tasks']
  7. )
  8. app.conf.update(
  9. CELERYD_PREFETCH_MULTIPLIER=2,
  10. CELERY_ROUTES={
  11. 'tasks.fun_1': {
  12. 'queue': "q_1"
  13. },
  14. 'tasks.fun_2': {
  15. 'queue': "q_2"
  16. }
  17. }
  18. )
  19. platforms.C_FORCE_ROOT = True
  20.  
  21. @app.task
  22. def fun_1(n):
  23. print "(((((((((((((((func_1", n
  24. time.sleep(20)
  25. return 1
  26.  
  27. @app.task
  28. def fun_2(n):
  29. print n, ")))))))))))))))"
  30. return 2

调用

  1. >>> from tasks import *
  2. >>> fun_1.delay(3)
  3. <AsyncResult: 609f2216-6785-409e-9f6f-85ae3fcce084>
  4. >>> fun_1.delay(3)
  5. <AsyncResult: 0230b8bd-b237-40ef-bc73-88929f8f8290>
  6. >>> fun_1.delay(3)
  7. <AsyncResult: 8fce172a-93c9-41f8-8c08-377a4363389c>
  8. >>> 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. easymock快速入门

    easymock是众多mock之中的很容易用的mock,今天刚开始学习,来个简单的教程.以购物车结算为例子,比如首先是每一个商品项的pojo. public class Item { private ...

  2. UIAlertView 点击按钮后控制其是否消失

    新建NotDismissAlertView类,继承UIAlertView. 设置控制是否消失的标示符 重写  在-(void)dismissWithClickedButtonIndex:(NSInte ...

  3. [MSP430] 对MSP430单片机__delay_cycles精确延时的说明及改正

    在这里, 我来讨论一下关于MSP430单片机使用__delay_cycles延时的问题. IAR for MSP430编译器提供了一个编译器内联的精确延时函数(并非真正的 函数)以提供用户精确延时使用 ...

  4. cron执行service

    在Cron的环境下,是没有定义路径的,所以,service xxx start等等要使用绝对路径 => /sbin/service xxx start service的路径可以用whereis ...

  5. SharePoint 关于拓扑错误的解决方案

    Issue Topology报错信息:SharePoint Web Services Round Robin Service Load Balancer Event: EndpointFailure. ...

  6. JSP相关知识

    1.JSP的3个编译指令 pag include taglib 2.JSP的7个动作指令 forward include useBean setProperty getProperty plugin ...

  7. UnicodeDecodeError: 'utf-8' codec can't decode byte

    for line in open('u.item'): #read each line whenever I run this code it gives the following error: U ...

  8. update关联其他表批量更新数据-跨数据库-跨服务器Update时关联表条件更新

    1.有时在做项目时会有些期初数据更新,从老系统更新到新系统.如果用程序循环从老系统付给新系统. 2.有时在项目中需要同步程序,或者自动同步程序时会有大量数据更新就可能用到如下方法了. 3.为了做分析, ...

  9. DCOS中监控和弹性伸缩方案经验

    监控的选型 我们的DCOS 主要是面向2种业务形态:互联网应用,NFV组件和相关的数据库.2种不同的业务虽然说都是跑在容器内部,但是其实需要监控的信息和指标都是各不相同.因此在选择监控方案的时候我们更 ...

  10. Android:使用 DownloadManager 进行版本更新,出现 No Activity found to handle Intent 及解决办法

    项目中,进行版本更新的时候,用的是自己写的下载方案,最近看到了使用系统服务 DownloadManager 进行版本更新,自己也试试. 在下载完成以后,安装更新的时候,出现了一个 crash,抓取的 ...