celery初识

celery

Celery是一个功能完备即插即用的异步任务队列系统。它适用于异步处理问题,当发送邮件、或者文件上传, 图像处理等等一些比较耗时的操作,我们可将其异步执行,这样用户不需要等待很久,提高用户体验。

Celery的特点是:

  1. 简单,易于使用和维护,有丰富的文档。

  2. 高效,单个celery进程每分钟可以处理数百万个任务。

  3. 灵活,celery中几乎每个部分都可以自定义扩展。

 任务队列是一种跨线程、跨机器工作的一种机制.
 任务队列中包含称作任务的工作单元。有专门的工作进程持续不断的监视任务队列,并从中获得新的任务并处理.
 celery通过消息进行通信,通常使用一个叫Broker(中间人)来协client(任务的发出者)和worker(任务的处理者).

相关依赖安装

pip install celery
pip install redis

celery.py

 #!/usr/bin/env python
 # -*- coding:utf-8 -*-
 ​
 from __future__ import absolute_import
 from celery import Celery
 ​
 app = Celery('mycelery', include=['mycelery.tasks'])
 ​
 app.config_from_object('mycelery.config')
 ​
 if __name__ == '__main__':
     app.start()

config.py

 #!/usr/bin/env python
 # -*- coding:utf-8 -*-
 ​
 from __future__ import absolute_import
 ​
 # 使用redis作为任务队列
 # 在celery4.x以后,就是BROKER_URL,如果是以前,需要写成CELERY_BROKER_URL
 # 无密码:BROKER_URL = 'redis://127.0.0.1:6379/0'
 BROKER_URL = 'redis://username:[email protected]:6379/0'
 # 使用redis存储任务执行结果,默认不使用,(如果涉及有返回值的函数情况下使用)
 CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/1'
 ​
 # 设置时区
 CELERY_TIMEZONE = 'Asia/Shanghai'
 # 启动时区设置
 CELERY_ENABLE_UTC = True
 ​
 # 并发的worker数量,也是命令行-c指定的数目,默认是服务器的内核数目
 # 事实上并不是worker数量越多越好,保证任务不堆积,加上一些新增任务的预留就可以了
 CELERYD_CONCURRENCY = 10
 # celery worker每次去redis取任务的数量,默认值就是4
 CELERYD_PREFETCH_MULTIPLIER = 4
 # 每个worker执行了多少次任务后就会死掉,建议数量大一些,默认是无限的
 CELERYD_MAX_TASKS_PER_CHILD = 200
 # celery任务执行结果的超时时间
 CELERY_TASK_RESULT_EXPIRES = 60 * 20
 # 单个任务的运行时间限制,否则会被杀死
 CELERYD_TASK_TIME_LIMIT = 60
 ​
 # 指定任务接受的序列化类型.
 CELERY_ACCEPT_CONTENT = ['application/json']
 ​
 # 将任务结果使用'pickle'序列化成'json'格式
 # 任务序列化方式
 CELERY_TASK_SERIALIZER = 'json'
 # 任务执行结果序列化方式
 CELERY_RESULT_SERIALIZER = 'json'
 # 也可以直接在Celery对象中设置序列化方式
 app = Celery('tasks', broker='redis://127.0.0.1:6379/1', task_serializer='yaml')
 # 常见的数据序列化方式
 binary: 二进制序列化方式;python的pickle默认的序列化方法;
 json:json 支持多种语言, 可用于跨语言方案,但好像不支持自定义的类对象;
 XML:类似标签语言;
 msgpack:二进制的类 json 序列化方案, 但比 json 的数据结构更小, 更快;
 yaml:yaml 表达能力更强, 支持的数据类型较 json 多, 但是 python 客户端的性能不如 json
 ​
 # 任务发送完成是否需要确认,对性能会稍有影响
 CELERY_ACKS_LATE = True
 ​
 # 压缩方案选择,可以是zlib, bzip2,默认是发送没有压缩的数据
 CELERY_MESSAGE_COMPRESSION = 'zlib'
 ​
 # 限制任务的执行频率
 # 下面这个就是限制tasks模块下的add函数,每秒钟只能执行10次
 CELERY_ANNOTATIONS = {'tasks.add':{'rate_limit':'10/s'}}
 # 或者限制所有的任务的刷新频率
 CELERY_ANNOTATIONS = {'*':{'rate_limit':'10/s'}}
 ​
 # 也可以设置如果任务执行失败后调用的函数
 def my_on_failure(self,exc,task_id,args,kwargs,einfo):
     print('task failed')
 CELERY_ANNOTATIONS = {'*':{'on_failure':my_on_failure}}
 ​
 # 间隔任务
 # 定时任务
 CELERYBEAT_SCHEDULE = {
     'add-every-30-seconds': {
          'task': 'mycelery.tasks.add',
          'schedule': timedelta(seconds=30),
          'args': (16, 16)
     },
     # Executes every Monday morning at 7:30 A.M
     'add-every-monday-morning': {
         'task': 'tasks.add',
         'schedule': crontab(hour=7, minute=30, day_of_week=1),
         'args': (16, 16),
     },
 }
 ​
 #设置默认的队列名称,如果一个消息不符合其他的队列就会放在默认队列里面,如果什么都不设置的话,数据都会发送到默认的队列中
 CELERY_DEFAULT_QUEUE = "default"
 ​
 # 或者配置成下面两种方式:
 # 配置队列(settings.py)
 CELERY_QUEUES = (
     Queue('default', 
         Exchange('default'), 
         routing_key='default'),
     Queue('for_task_collect', 
         Exchange('for_task_collect'), 
         routing_key='for_task_collect'),
     Queue('for_task_compute', 
         Exchange('for_task_compute'), 
         routing_key='for_task_compute'),
 )
 CELERY_QUEUES = {
     "default": { # 这是上面指定的默认队列
         "exchange": "default",
         "exchange_type": "direct",
         "routing_key": "default"
     },
     "topicqueue": { # 这是一个topic队列 凡是topictest开头的routing key都会被放到这个队列
         "routing_key": "topic.#",
         "exchange": "topic_exchange",
         "exchange_type": "topic",
     },
     "task_eeg": { # 设置扇形交换机
         "exchange": "tasks",
         "exchange_type": "fanout",
         "binding_key": "tasks",
     },
 }
 ​
 #路由(哪个任务放入哪个队列)
 CELERY_ROUTES = {
     'umonitor.tasks.multiple_thread_metric_collector': 
     {
         'queue': 'for_task_collect', 
         'routing_key': 'for_task_collect'
     },
     'compute.tasks.multiple_thread_metric_aggregate': 
     {
         'queue': 'for_task_compute', 
         'routing_key': 'for_task_compute'
     },
     'compute.tasks.test': 
     {
          'queue': 'for_task_compute',
          'routing_key': 'for_task_compute'
     },
 }

celery.exchange

 # Exchange的值为:
 1、fanout(广播式),它不需要指定路由就会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中
 例如:
 CELERY_QUEUES = (
     Queue('for_adds',Exchange('for_adds',type='fanout')),
     Queue('for_send_emails', Exchange('for_adds',type='fanout')),
     Queue('add', Exchange('for_adds',type='fanout')),
 )
 CELERY_ROUTES = {
     'celery_test.tasks.add': {'exchange':'for_adds'},
     'celery_test.tasks.send_mail': {'exchange':'for_adds',},
     'celery_test.tasks.adds': {'exchange':'for_adds',},
 }
 ​
 2、direct,direct类型的Exchange路由规则也很简单,它会把消息路由到那些binding key与routing key完全匹配的Queue中
 例如:
 CELERY_QUEUES = (
     Queue('for_adds',Exchange('for_adds',type='direct'), routing_key='adds'),
     Queue('for_send_emails', Exchange('for_adds',type='direct'), routing_key='email'),
     Queue('add', Exchange('for_adds',type='direct'), routing_key='add'),
 )
 CELERY_ROUTES = {
     'celery_test.tasks.add': {'exchange':'for_adds','routing_key':'add'},
     'celery_test.tasks.send_mail': {'exchange':'for_adds','routing_key':'email'},
     'celery_test.tasks.adds': {'exchange':'for_adds','routing_key':'add'},
 }
 ​
 3、topic,topic类型的Exchange在匹配规则上进行了扩展,它与direct类型的Exchage相似,也是将消息路由到binding key与routing key相匹配的Queue中,但这里的匹配规则有些不同,它约定
 3.1 routing key为一个句点号“. ”分隔的字符串(我们将被句点号“. ”分隔开的每一段独立的字符串称为一个单词),如“*.task.*”、"*.*.email"、“*.add”
 3.2 binding key与routing key一样也是句点号“. ”分隔的字符串
 3.3 binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“*”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)
 例如:
 CELERY_QUEUES = (
     Queue('for_adds',Exchange('for_adds',type='topic'), routing_key='*.task.*'),
     Queue('for_send_emails', Exchange('for_adds',type='topic'), routing_key='*.*.email'),
     Queue('add', Exchange('for_adds',type='topic'), routing_key='*.add'),
 )
 CELERY_ROUTES = {
     'celery_test.tasks.add': {'exchange':'for_adds','routing_key':'q.task.email'},
     'celery_test.tasks.send_mail': {'exchange':'for_adds','routing_key':'a.task.e'},
     'celery_test.tasks.adds': {'exchange':'for_adds','routing_key':'b.add'},
 }
 该路由的设置,adds会到add队列,send_mail会到for_adds队列,add会到for_adds和for_send_emails队列

tasks.py

 #!/usr/bin/env python
 # -*- coding:utf-8 -*-
 ​
 from __future__ import absolute_import
 from mycelery.celery import app
 ​
 @app.task
 def add(x, y):
     return x + y

项目调用

 # 1. 声明一个和celery一模一样的任务函数,导包来解决
 from mycelery.sms.tasks import send_sms
 ​
 # 2. 调用任务函数,发布任务
 send_sms.delay(mobile,code)
 # send_sms.delay() 如果调用的任务函数没有参数,则不需要填写任何内容

celery启动命令

 celery -A mycelery.main worker --loglevel=info
 # 定时任务
 celery -A mycelery.main worker -B -l info
 # windows
 celery -A mycelery.main worker --pool=solo -l info
 # 其他参数
 multi start     #后台启动
 -c 4    # 工人数量
 # 任务清除
 celery purge
 # 启动不同worker处理不同队列的任务
 # 指定worker_compute去处理队列for_task_compute的任务
 python manage.py celery worker -E -l INFO -n worker_compute -Q for_task_compute
 # 指定worker_collect去处理队列for_task_collect的任务
 python manage.py celery worker -E -l INFO -n worker_collect -Q for_task_collect

与django使用时

celery.py加上

# 把celery和django进行组合,识别和加载django的配置文件
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'api.settings.dev')

成功截图

celery初识_第1张图片

你可能感兴趣的:(python)