python Celery 基础

介绍

Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, 例子:

  • 你想对100台机器执行一条批量命令,可能会花很长时间 ,但你不想让你的程序等着结果返回,而是给你返回 一个任务ID,你过一段时间只需要拿着这个任务id就可以拿到任务执行结果, 在任务执行ing进行时,你可以继续做其它的事情。

Celery 在执行任务时需要通过一个消息中间件来接收和发送任务消息,以及存储任务结果, 一般使用rabbitMQ or Redis,后面会讲

Celery有以下优点:

  • 简单:一单熟悉了celery的工作流程后,配置和使用还是比较简单的
  • 高可用:当任务执行失败或执行过程中发生连接中断,celery 会自动尝试重新执行任务
  • 快速:一个单进程的celery每分钟可处理上百万个任务
  • 灵活: 几乎celery的各个组件都可以被扩展及自定制

 

安装及基本使用

安装

pip3 install celery
pip3 install eventlet pip install
-U "celery[redis]"  #安装redis组件,使用redis做broker

 

配置

可以使用redis和rabbitmq做broker

#配置rabbitmq
    broker_url = 'amqp://guest:guest@localhost:5672//'

#配置无密码redis
    app.conf.broker_url = 'redis://localhost:6379/0'

#配置有密码redis
    app.conf.broker_url = redis://:password@hostname:port/db_number

#获取每个任务的执行结果,配置任务结果的存放位置   app.conf.result_backend = 'redis://localhost:6379/0'

 

简单使用测试

#cat test.py

from celery import Celery

app = Celery('tasks',

             broker='redis://10.10.10.11',

             backend='redis://10.10.10.11')

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

#启动Celery Worker来开始监听并执行任务 celery -A test worker --loglevel=info -P eventlet    #这里的test为上面的test.py执行文件

新建终端执行命令

D:\django-project\wechat>python
Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from test import add
>>> add.delay(4, 4)
<AsyncResult: c740d5fb-d7aa-4564-94b0-1e7258bbd23d>
>>>

日志

[2018-05-15 16:39:36,845: INFO/MainProcess] Received task: test.add[c740d5fb-d7aa-4564-94b0-1e7258bbd23d]
[2018-05-15 16:39:36,846: WARNING/MainProcess] running...
[2018-05-15 16:39:36,847: WARNING/MainProcess] 4
[2018-05-15 16:39:36,847: WARNING/MainProcess] 4
[2018-05-15 16:39:36,883: INFO/MainProcess] Task test.add[c740d5fb-d7aa-4564-94b0-1e7258bbd23d] succeeded in 0.046000000002095476s: 8

 

如果报错

[2018-05-15 16:36:03,274: INFO/MainProcess] Received task: test.add[f2e6e1da-481f-45e4-a8db-3d1becd18b56]
[2018-05-15 16:36:03,328: ERROR/MainProcess] Task handler raised error: ValueError('not enough values to unpack (expected 3, got 0)',)
Traceback (most recent call last):
  File "c:\users\administrator\appdata\local\programs\python\python36\lib\site-packages\billiard\pool.py", line 358, in workloop
    result = (True, prepare_result(fun(*args, **kwargs)))
  File "c:\users\administrator\appdata\local\programs\python\python36\lib\site-packages\celery\app\trace.py", line 525, in _fast_trace_task
    tasks, accept, hostname = _loc
ValueError: not enough values to unpack (expected 3, got 0)

解决办法

pip3 install eventlet

 

命令说明

result = func.delay("参数")

result.ready()        #表示查看函数是否执行完毕,是否返回结果

result.get(timeout=1)    #设置超时时间

 

执行命令示例

from celery import Celery
import subprocess

app = Celery('tasks',
             broker='redis://10.10.10.11',
             backend='redis://10.10.10.11')
@app.task
def add(x, y):
    print("running...", x, y)
    return x + y

@app.task
def cmd_run(cmd):
    result = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    return result.stdout.read().decode("utf-8")    #返回的结果为bytes类型,转换成str

 

启动

celery -A test worker --loglevel=info -P eventlet

 

打开终端执行

from test import cmd_run
cmd_run.delay('ipconfig')

 

项目中使用celery

将celery配置成一个应用,目录结构如下

celery_proj/__init__.py          #项目名称自己定义
    /celery.py
    /tasks.py

celery_proj/celery.py内容

from __future__ import absolute_import, unicode_literals

from celery import Celery 

app = Celery('celery_proj',                           #这里proj为项目名称

             broker='amqp://',                      #rabbitmq或redis地址

             backend='amqp://',

             include=['proj.tasks'])

app.conf.update(
    result_expires=3600,
)

if __name__ == '__main__':

    app.start()

celery_proj/tasks.py中的内容

from __future__ import absolute_import, unicode_literals
from .celery import app
import subprocess

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

@app.task
def mul(x, y):
    return x * y

@app.task
def cmd_run(cmd):
    result = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    return result.stdout.read().decode("utf-8")

 

启动

celery -A proj worker -l info -P eventlet     #这里启动就要写项目名称了

 

日志

D:\django-project\wechat>celery -A celery_pro worker -l info -P eventlet

 -------------- celery@R201611161646 v4.1.0 (latentcall)
---- **** -----
--- * ***  * -- Windows-7-6.1.7601-SP1 2018-05-16 10:47:55
-- * - **** ---
- ** ---------- [config]
- ** ---------- .> app:         celery_pro:0x4635c50
- ** ---------- .> transport:   redis://10.10.10.11:6379//
- ** ---------- .> results:     redis://10.10.10.11/
- *** --- * --- .> concurrency: 8 (eventlet)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** -----
 -------------- [queues]
                .> celery           exchange=celery(direct) key=celery


[tasks]
  . celery_pro.test_celery.add
  . celery_pro.test_celery.cmd_run
  . celery_pro.test_celery.mul

[2018-05-16 10:47:55,268: INFO/MainProcess] Connected to redis://10.10.10.11:6379//
[2018-05-16 10:47:55,296: INFO/MainProcess] mingle: searching for neighbors
[2018-05-16 10:47:56,455: INFO/MainProcess] mingle: all alone
[2018-05-16 10:47:56,504: INFO/MainProcess] pidbox: Connected to redis://10.10.10.11:6379//.
[2018-05-16 10:47:56,535: INFO/MainProcess] celery@R201611161646 ready.
[2018-05-16 10:48:09,373: INFO/MainProcess] Received task: celery_pro.test_celery.cmd_run[fcfbe7e7-9ced-40b2-a231-d2f1f712a846]
[2018-05-16 10:48:09,482: ERROR/MainProcess] Task celery_pro.test_celery.cmd_run[fcfbe7e7-9ced-40b2-a231-d2f1f712a846] raised unexpected: UnicodeDecodeError('utf-8', b' \xc7\xfd\xb6\
xaf\xc6\xf7 D \xd6\xd0\xb5\xc4\xbe\xed\xca\xc7 \xc8\xed\xbc\xfe\r\n \xbe\xed\xb5\xc4\xd0\xf2\xc1\xd0\xba\xc5\xca\xc7 0E89-3B03\r\n\r\n D:\\django-project\\wechat \xb5\xc4\xc4\xbf\xc2
\xbc\r\n\r\n2018/05/16 \xd6\xdc\xc8\xfd  10:37    <DIR>          .\r\n2018/05/16 \xd6\xdc\xc8\xfd  10:37    <DIR>          ..\r\n2018/05/16 \xd6\xdc\xc8\xfd  10:47    <DIR>
.idea\r\n2018/05/16 \xd6\xdc\xc8\xfd  10:45    <DIR>          celery_pro\r\n2018/05/10 \xd6\xdc\xcb\xc4  15:03            12,288 db.sqlite3\r\n2018/05/10 \xd6\xdc\xcb\xc4  11:37
          249 manage.py\r\n2018/05/10 \xd6\xdc\xcb\xc4  14:17    <DIR>          static\r\n2018/05/11 \xd6\xdc\xce\xe5  16:29    <DIR>          templates\r\n2018/05/15 \xd6\xdc\xb6\xf
e  17:41             1,216 test.py\r\n2018/05/11 \xd6\xdc\xce\xe5  16:29    <DIR>          web\r\n2018/05/10 \xd6\xdc\xcb\xc4  16:45    <DIR>          wechat\r\n2018/05/15 \xd6\xdc\x
b6\xfe  17:43    <DIR>          __pycache__\r\n               3 \xb8\xf6\xce\xc4\xbc\xfe         13,753 \xd7\xd6\xbd\xda\r\n               9 \xb8\xf6\xc4\xbf\xc2\xbc 226,018,455,552
\xbf\xc9\xd3\xc3\xd7\xd6\xbd\xda\r\n', 1, 2, 'invalid continuation byte')
View Code

 

后台启动

celery multi start w1 -A proj -l info      #multi表示可启动多个 w1 表示自定义的启动名称 -A 项目名
celery  multi restart/stop w1 -A proj -l info    #重启/关闭

 

posted @ 2018-05-16 11:14  FRESHMANS  阅读(451)  评论(0)    收藏  举报