celery入门

1.安装各种扩展

pip install celery[gevent]

2.demo

celeryconfig.py

CELERY_ACCEPT_CONTENT = ['json']
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_EVENT_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'

# maybe usefull later
# CELERY_ANNOTATIONS = {
#     'celerytasks.add': {'rate_limit': '2/m'}
# }


celerytasks.py

#codeing=utf8
import os
import sys
from celery import Celery
sys.path.insert(0, os.path.dirname(__file__))


REDIS_URL = 'redis://:redispasswd@127.0.0.1:6379/0'
app = Celery('celerytasks', backend=REDIS_URL, broker=REDIS_URL)
app.config_from_object('celeryconfig')

@app.task(bind=True)
def add(self, x, y):
    return x + y

3.运行

启动worker   消费者

celery --app=celerytasks worker --loglevel=info

启动 生产者 命令行

[(pyenv27) BJ****:scelery ****$ python
Python 2.7.10 (default, Oct 23 2015, 19:19:21) 
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from celerytasks import add
>>> add.name
'celerytasks.add'
>>> add.delay(1, 2).get()
3


4.与Django集成

pip install django-celery

在view层代码里import task函数,并调用即可,类似命令行。只不过把调用celery task由命令行换成view 函数

更多功能:使用Django的settings做为celery配置,使用Django ORM DB等


5.与tornado集成

#coding=utf8
from tornado import gen
from tornado.web import asynchronous, RequestHandler
from celerytasks import add


class TestCeleryHandler(RequestHandler):
    @asynchronous
    @gen.coroutine
    def get(self):
        x = self.get_argument("x", 0)
        y = self.get_argument("y", 0)
        result = yield self._call_task(int(x), int(y))
        self.write({"result": result})
        self.finish()

    @gen.coroutine
    def _call_task(self, x, y):
        result = add.delay(x, y)
        raise gen.Return(result.get())
按照文档中的写法报错,task function不可序列化,所以才有了上面的丑恶代码。文档中写法

    @asynchronous
    @gen.coroutine
    def get(self):
        response = yield gen.Task(celerytask.add.apply_async, args=[3,4])
        self.write(str(response.result))
        self.finish()
本人不才,按文档写一直报错:

TypeError: <function wrapper at 0x10f0c1cf8> is not JSON serializable

就是yield gen.Task(celerytask.add.apply_async, args=[3,4])一句中的celerytask.add.apply_async不可序列化。大神若知,望留言指点



没有什么高深的,就是在request handler里yield调用celery task。只需要注意使用coroutine避免阻塞

当然每个task都要写一个handler来调用,确实很麻烦。tornado-celery可以帮助完成上面无聊的handler代码

pip install tornado-celery

pip install tornado-redis <如果broker是redis,必须安装>

安装完了,一行代码也不用写,

直接启动web服务

python -m tcelery --port=7777 --app=celerytasks

这行命令接受一个app参数就是你的celery task app名,启动了一个tornado web服务,提供如下URL让你访问

/apply/(.*)/                     同步提交任务

/async_apply/(.*)/          异步提交任务

/tasks/result/(.*)/            获取结果

/tasks/revoke/(.*)/          取消任务


curl -X POST -d '{ "args": [ 1, 2 ] }' http://localhost:7777/apply-async/celerytasks.add/

返回{"task-id": "013864e1-a6b2-47cd-b78f-c43adc134e08", "state": "PENDING"}

curl -X GET  http://localhost:7777/tasks/result/013864e1-a6b2-47cd-b78f-c43adc134e08    查看结果


少写了handler代码,代价就是不灵活,参数固定死了是args , kwargs.此外,每个http请求只能invoke一个task,不能自定义chain,group,map等等高级任务调度


6.redis 变化

当worker启动时,会连接broker,此处使用redis。可命令行查看keys,默认worker启动会创建3个set

redis-cli -a redispasswd
127.0.0.1:6379> keys *
1) "_kombu.binding.celery"
2) "_kombu.binding.celeryev"
3) "_kombu.binding.celery.pidbox"
当有任务提交后,会再创建一个队列,默认key名叫celery,生产者将消息push进来,消费者将消息pop取走。并且会以每个任务的id做为key,以该任务的状态(结果)的序列化值作为value(字符串类型),写到result backend

[127.0.0.1:6379> type celery-task-meta-9a4fa89c-2996-444c-9983-b24fec25f14e
string
127.0.0.1:6379> get celery-task-meta-9a4fa89c-2996-444c-9983-b24fec25f14e
"{\"status\": \"SUCCESS\", \"traceback\": null, \"result\": 5000, \"children\": []}"





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值