celery + redis

celery 是一种分布式任务队列

以下是需要理解的几种概念

任务:消息队列里面的一个工作单元

分布式:独立Worker可以布在不同的机器上,一个worker可以指定并发数

Broker:消息通讯的中间人,主要有RabbitMQ, Redis(本例用的是redis,较为轻量级)

beat:定时任务,可以指定任务若干秒后,或定时时间执行

 

安装就不说了,直接用 pip 就可以了,也可以安装在venv上

先创建一下结构

celery_proj/
    __init__.py

    beat_tasks.py #定时任务放在这里

   celery.py #启动脚本
 
    config.py #配置

    tasks.py  #非定时任务,手动调的等其他任务放在这个里

        

celery.py

#!/mfs/lib/Envs/whx/bin/python2.7
# -*-coding:utf-8 -*-

# Created on 2016-05-09

# @author: whx

from __future__ import absolute_import
from celery import Celery

#指定任务py
app = Celery('celery_proj', include=['celery_proj.tasks', 'celery_proj.beat_tasks'])
#指定配置
app.config_from_object('celery_proj.config')



#def getActiveInfo(timeout=1):
#    active_dict = app.control.inspect(timeout=timeout).active()
#    return active_dict
    

#def removeTask(task_id):
#    print app.control.revoke(task_id, terminate=True)


if __name__ == '__main__':
    app.start()

beat_tasks.py

#!/mfs/lib/Envs/whx/bin/python2.7
# -*-coding:utf-8 -*-

# Created on 2016-05-09

# @author: whx

from __future__ import absolute_import
from celery_proj.celery import app
import datetime
import subprocess
import os


def run_cmd(cmd):
    "运行系统命令"
    pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = pipe.communicate()
    errcode = pipe.wait()
    if errcode != 0:
        msg = "command failed:\n%s\n" % ' '.join(cmd)
        if stdout:
            msg += "Standard output:\n%s\n" % stdout
        if stderr:
            msg += "Standard error:\n%s\n" % stderr
        raise OSError, msg
    return stdout, stderr



def get_last_hour():
    return (datetime.datetime.today() - datetime.timedelta(hours=1)).strftime("%Y%m%d%H")


#定义每小时日志ETL任务
@app.task(name='log_clean')
def log_clean_traffic():
    yyyymmddhh = get_last_hour()
    tag_dir= os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
    cmd = "bash  %s/run_sh/logformat.sh  traffic  %s"%(tag_dir, yyyymmddhh)
    #print cmd
    run_cmd(['sh', '-c', cmd])

tasks.py

from __future__ import absolute_import
from celery_proj.celery import app


#定义任务超时时间
#bind 绑定一个任务实例,self
#max_retries 是重新尝试的次数
#default_retry_delay 任务重新尝试的时间间隔6秒
#异常处理的countdown,时间间隔10秒,优先于default_retry_delay
#expires:任务运行的时间限制,超过300秒,任务会直接revoke
#没有指定任务名默认为dologic
@app.task(bind=True, max_retries=3,default_retry_delay=6, expires=300)
def dologic(self, task_name, args_json):
    cmd = "bash /mfs/home/whx/Script/spark/spark_run.sh  %s"%(task_name, args_json)
    try:
        return run_cmd(['sh', '-c', cmd])
    except Exception as exc:
        raise self.retry(exc=exc, countdown=10)

config.py

#!/mfs/lib/Envs/whx/bin/python2.7
# -*-coding:utf-8 -*-

# Created on 2016-05-09

# @author: whx


from __future__ import absolute_import
from celery.schedules import crontab

#执行结果保存的路径
CELERY_RESULT_BACKEND =  'redis://:pwd@host:port/0'
#中间人
BROKER_URL =  'redis://:pwd@host:port/12'
#序列化
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_ACCEPT_CONTENT=['json']
#结果保存的时间
CELERY_TASK_RESULT_EXPIRES = 86400  # 24 hours.
CELERY_TIMEZONE = 'Asia/Shanghai'  # 时区

#queue 定义执行的队列,启动celery时可以指定队列名
CELERY_ROUTES = {
        'celery_proj.tasks.dologic': {'queue': 'cq_170'},
        'log_clean': {'queue': 'cq_170'},
    }


CELERYBEAT_SCHEDULE = {
        #定义每小时的10分执行
        'log_clean': {
            "task": "log_clean",
            "schedule": crontab(minute=10),
            "args": ()
            },
        }

另外的:

依赖任务用chain,执行结果可以一级级往下传

并列任务用group

from celery import task, group, chain

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



@task(name="main1")
def test1():
    
    #链级 结果向下传递: 2 + 2 + 4 + 8 = 16
    res = chain(add.s(2, 2), add.s(4), add.s(8))()
    res = (add.s(2, 2) | add.s(4) | add.s(8))()

    #链级 结果没有传递:9
    res = chain(add.si(2, 2), add.si(4, 4), add.si(1, 8))()
    res = (add.si(2, 2) | add.si(4, 4) | add.si(1, 8))()

    return res
    


@task(name="main2")
def test2():
    
    #并列执行
    join = group([
             add.s(2,2),
             add.s(4,4),
             add.s(8,8),
             add.s(16,16),

        ])()

    return res



#先依赖后并行
#res = (add.s(4, 4) | group(add.si(i, i) for i in xrange(10)))()

 

调试运行:


python -m celery -A celery_proj worker -E  -B -Q cq_170 -l info --concurrency=10 -n worker1@%h

#启动worker 
#concurrency 并发数
#-E 启动事件
#-B 同时启动beat,既 定时任务
#-Q 指定队列名:cq_170

#%h	worker1@%h	worker1@george.example.com
#%n	worker1@%n	worker1@george
#%d	worker1@%d	worker1@example.com

后台运行:

python -m celery multi start whxpc  -A celery_proj  -E  -B -Q cq_170 -c10 -n worker1@%h -l debug \
  --logfile="./log/celery.log" --pidfile="./celery.pid"

 

官方文档:http://docs.celeryproject.org/en/latest/

转载于:https://my.oschina.net/whx403/blog/829666

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值