1.缓存

  当一些数据需要固定地且频繁访问数据库时,需要使用到接口缓存。

  以轮播图为例,每个用户都会访问首页,首页的轮播图长时间不会改变,所以可以使用cache,将固定数据保存到缓存中(redis),第二次调用数据库的时候,就可以从缓存中调用数据,使得并发量增加,保护数据库。

  但是一直访问缓存,数据库改变了数据,那么本来的页面就不会被改变。所以要使用celery定时地访问数据库,修改数据。

2.celery的使用场景

  celeryd使用场景除了运行定时任务之外们还可以执行异步任务。

  在官网可以找到开发文档:

Celery 官网:http://www.celeryproject.org/

Celery 官方文档英文版:http://docs.celeryproject.org/en/latest/index.html

Celery 官方文档中文版:http://docs.jinkan.org/docs/celery/

  每一个celery都由三部分组成:

  1.消息中间件

  Celery本身不提供消息服务,但是可以方便的和第三方提供的消息中间件集成。包括,RabbitMQ, Redis等等。

  2.任务执行单元

  Worker是Celery提供的任务执行的单元,worker并发的运行在分布式的系统节点中。

  3.任务结果存储

  Task result store用来存储Worker执行的任务的结果,Celery支持以不同方式存储任务的结果,包括AMQP, redis等。

三。celery的装配

  下载celery

pip install celery

消息中间件:RabbitMQ/Redis

app=celery.Celery('任务名', broker='xxx', backend='xxx', include=['xxx', 'xxx'])

  包架构封装

project
├── celery_task # celery包
│ ├── __init__.py # 包文件
│ ├── celery.py # celery连接和配置相关文件,且名字必须交celery.py
│ └── tasks.py # 所有任务函数
├── add_task.py # 添加任务
└── get_result.py # 获取结果

  将celery_task包放到大项目下,这个包名可以随意,但是启动任务的时候需要用到,

  其中的celery必须使用该名字,

  启动celery的语句如下:

# 2)启动celery(app)服务:
# 非windows
# 命令:celery worker -A celery_task -l info
# windows:
# pip3 install eventlet
# celery worker -A celery_task -l info -P eventlet # 3)添加任务:手动添加,要自定义添加任务的脚本,右键执行脚本 # 4)获取结果:手动获取,要自定义获取任务的脚本,右键执行脚本

  如果需要自动执行添加任务,需要启动一个添加任务的服务。

# 命令: celery beat -A celery_task -l info

  celery_tesk时celery总文件夹。

  启动worker就可以随时从任务列表中获取任务执行。

  1.celery

  celery中需要配置django相关的环境以及celery的环境。


import os,django
# import sys
# sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Wechatshop.settings")
django.setup()
from celery import Celery

broker = 'redis://127.0.0.1:6379/1'
backend = 'redis://127.0.0.1:6379/2'
app = Celery(broker=broker, backend=backend, include=['celery_task.tasks']) # 时区
app.conf.timezone = 'Asia/Shanghai'
# 是否使用UTC
app.conf.enable_utc = False # 任务的定时配置
from datetime import timedelta
from celery.schedules import crontab
app.conf.beat_schedule = {
'low-task': { # 新的任务名
'task': 'celery_task.tasks.low',# 任务源
'schedule': timedelta(seconds=3),# 定时时间
# 'schedule': crontab(hour=8, day_of_week=1), # 每周一早八点
'args': (300, 150), # 定时参数
}
}

  如果需要添加定时任务,需要做以上配置

  2.tasks

  任务源,文件名可以改变,但是其他地方调用的时候需要改变。

  在任务函数之气那需要调用语法糖。

from .celery import app
import time
@app.task
def add(n, m):
print(n)
print(m)
time.sleep(10)
print('n+m的结果:%s' % (n + m))
return n + m @app.task
def low(n, m):
print(n)
print(m)
print('n-m的结果:%s' % (n - m))
return n - m from home.models import Banner
from settings.const import BANNER_COUNT # 轮播图最大显示条数
from home.serializers import BannerModelSerializer
from django.core.cache import cache
@app.task
def update_banner_list():
# 获取最新内容
banner_query = Banner.objects.filter(is_delete=False, is_show=True).order_by('-orders')[:BANNER_COUNT]
# 序列化
banner_data = BannerModelSerializer(banner_query, many=True).data
for banner in banner_data:
banner['image'] = 'http://127.0.0.1:8000' + banner['image']
# 更新缓存
cache.set('banner_list', banner_data)
return True

  3.add_task

  当需要添加任务的时候,直接在需要添加任务的地方调用任务文件夹下的任务名,执行对于的函数:

from celery_task import tasks
# 添加立即执行任务
t1 = tasks.add.delay(10, 20)
t2 = tasks.low.delay(100, 50)
print(ti.id)

  返回值为id,delay代表添加及时任务。括号中的时任务需要的参数。

  添加定时任务需要在celery中配置。在启动该任务的时候,需要beat的帮助才能定时地添加任务,启动任务。

# 命令: celery beat -A celery_task -l info

  添加延时任务。

  需要设定eta_second,将时间转换为celery需要的时间格式,单位为秒

# 添加延迟任务
from datetime import datetime, timedelta
def eta_second(second):
ctime = datetime.now()
utc_ctime = datetime.utcfromtimestamp(ctime.timestamp())
time_delay = timedelta(seconds=second)
return utc_ctime + time_delay tasks.low.apply_async(args=(200, 50), eta=eta_second(10))

  关键函数为apply_async.

  扩展:

  动态添加定时任务,可以使用redis后端链接mysql,参考项目。

https://github.com/sibson/redbeat

  

  创建一个文件夹如上,celery中是框架内容和环境,tasks则需要编写语法糖装饰过的函数:

from .celery import app
import time
@app.task
def add(n, m):
print(n)
print(m)
time.sleep(10)
print('n+m的结果:%s' % (n + m))
return n + m

  如果需要在django中运行,需要引入django的环境。

  启动celey:

  需要安装一个线程相关的模块

pip install eventlet

  启动work

celery worker -A celery_task -l info -P eventlet

  一般在项目目录下启动,如果启动失败,就指定到celery的文件夹:celey_task.celery

  启动beat:

celery beat -A celery_task -l info

  注意环境的搭建路径

  1.及时任务的添加:

from celery_task.tasks import test
t1 = test.delay()

  括号中传递的是即使任务函数的参数

  2.延时任务的添加:

from datetime import datetime, timedelta
def eta_second(second):
ctime = datetime.now()
utc_ctime = datetime.utcfromtimestamp(ctime.timestamp())
time_delay = timedelta(seconds=second)
return utc_ctime + time_delay tasks.low.apply_async(args=(200, 50), eta=eta_second(10))

  apply_async的第一个参数是运行函数的参数,第二个参数则是时间类型的时间,需要给指定的运行时间。

  3.定时任务:

# 任务的定时配置
from datetime import timedelta
from celery.schedules import crontab
app.conf.beat_schedule = {
'printnb-task': {
'task': 'celery_task.tasks.printnb',
'schedule': timedelta(seconds=10), # 配置任务时间
# 'schedule': crontab(hour=8, day_of_week=1), # 每周一早八点
'args': (), # 执行任务的参数
}
}

  其中,任务函数的返回值可以是任意的。

  获取函数结果:

from celery_task.celery import app

from celery.result import AsyncResult

id = '21325a40-9d32-44b5-a701-9a31cc3c74b5'
if __name__ == '__main__':
async = AsyncResult(id=id, app=app)
if async.successful():
result = async.get()
print(result)
elif async.failed():
print('任务失败')
elif async.status == 'PENDING':
print('任务等待中被执行')
elif async.status == 'RETRY':
print('任务异常后正在重试')
elif async.status == 'STARTED':
print('任务已经开始被执行')

  其中

as1 = AsyncResult(id=id,app=app)

  as1打印出来的就是任务id,开发者可以根据任务id(as1.id)

  可以根据启动任务时获取的返回值对象获取id,再使用AsyncResult生成返回对象。

  async.successful():

  检测任务是否完成,返回布尔值。

  async.failed():

  检测任务是否失败,返回布尔值。

  result = async.get()

  获取任务执行之后的结果就是任务函数的返回值

  async.status

  返回任务的状态。

day82_10_31celery的使用的更多相关文章

随机推荐

  1. 运行springboot项目报错:Field userMapper in XX required a bean of type 'xx' that could not be found.

    运行springboot项目报错: *************************** APPLICATION FAILED TO START ************************** ...

  2. matlab键盘快捷键无法使用的解决办法

    打开matlab,在主页里点击 预设/preferences 左栏找 键盘/keyboard 点开键盘点击 快捷方式/shortcuts 在右边 活动设置 /Active settings 里选择 W ...

  3. python第三次作业-mooc笔记

    1.注册中国大学MOOC 2.选择北京理工大学嵩天老师的<Python网络爬虫与信息提取>MOOC课程3.学习完成第0周至第4周的课程内容,并完成各周作业 4.提供图片或网站显示的学习进度 ...

  4. 成为杰出Java开发人员的10个步骤

    在优锐课的学习分享中,讨论了如果你是Java开发人员并且对技术充满热情,则可以按照以下十个步骤进行操作,这可以使你成为杰出的Java开发人员. 1.具有扎实的基础和对OO原理的理解 对于Java开发人 ...

  5. 从游击队到正规军(二):马蜂窝旅游网的IM客户端架构演进和实践总结

    一.引言 移动互联网技术改变了旅游的世界,这个领域过去沉重的信息分销成本被大大降低.用户与服务供应商之间.用户与用户之间的沟通路径逐渐打通,沟通的场景也在不断扩展.这促使所有的移动应用开发者都要从用户 ...

  6. KeContextToKframes函数逆向

    在逆向_KiRaiseException(之后紧接着就是派发KiDispatchException)函数时,遇到一个 KeContextToKframes 函数,表面意思将CONTEXT转换为 TRA ...

  7. [反汇编] 获取上一个栈帧的ebp

    使用代码 lea ecx, [ebp+4+参数长度] 就可以实现. 如下图,理解栈帧的结构,很好理解. 虽然也是 push param的,但这部分在恢复时被调用函数会恢复的,因此这并不算esp的值. ...

  8. 前端之CSS1

    CSS基本语法和引入方式 CSS介绍 为了让网页元素的样式更加丰富,也为了让网页的内容和样式能拆分开,CSS由此而诞生,CSS是 Cascading Style Sheets 的首字母缩写,意思是层叠 ...

  9. MySQL EXPLAIN 语句

    对于 MySQL 在执行时来说,EXPLAIN 功能上与 DESCRIBE 一样.实际运用中,后者多用来获取表的信息,而前者多用于展示 MySQL 会如何执行 SQL 语句(Obtaining Exe ...

  10. WebService发布服务例子

    import javax.jws.WebMethod; import javax.jws.WebService; @WebService public interface WebServiceI { ...