django社交类程序笔记(8)Celery异步任务
celery 异步任务,耗时操作可以使用。
同步就是一个任务一个任务按顺序做,异步就是做一会A,做一会B,可以换着做任务。
任务模块 Task
包含异步任务和定时任务。其中, 异步任务通常在业务逻辑中被触发并发往任务队列, ⽽定时任务由 Celery Beat 进程周期性地将任务发往任务队列。
消息中间件 Broker
Broker, 即为任务调度队列, 接收任务⽣产者发来的消息(即任务), 将任务存⼊队列。Celery 本身不提供队列服务, 官⽅推荐使⽤ RabbitMQ 和 Redis 等。
任务执⾏单元 Worker
Worker 是执⾏任务的处理单元, 它实时监控消息队列, 获取队列中调度的任务, 并执⾏它。
任务结果存储 Backend
Backend ⽤于存储任务的执⾏结果, 以供查询。同消息中间件⼀样, 存储也可使⽤
RabbitMQ, Redis 和 MongoDB 等。
可以参考这里
这里涉及celery问题和redis,及装饰器知识点,
本项目继续:
在主项目中创建文件夹worker,新建__init__.py和config.py文件
init.py中添加代码:
import os
from celery import Celery
# 设置环境变量,加载django的setting
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'spiter.settings') # 可以复制wsgi.py
# 创建Celery Application
celery_app = Celery('spiter')
celery_app.config_from_object('worker.config')
celery_app.autodiscover_tasks()
def call_by_worker(func):
"""将任务在Celery中异步执行"""
task = celery_app.task(func)
return task.delay
config.py中添加代码:
broker_url = 'redis://127.0.0.1:6379/0'
broker_pool_limit = 1000 # Borker 连接池,默认是10
timezone = 'Asia/Shanghai'
accept_content = ['pickle', 'json']
task_serializer = 'pickle'
result_expires = 3600 # 任务过期时间
result_backend = 'redis://127.0.0.1:6379/0'
result_serializer = 'pickle'
result_cache_max = 10000 # 任务结果最⼤缓存数量
worker_redirect_stdouts_level = 'INFO'
当发送短信时,会交给celery来做,不是django做。
缓存,在logic.py中增加缓存如下:
from django.core.cache import cache
...
@call_by_worker
def send_verify_code(phonenum): # 手机号拼进来
vcode = gen_verify_code() # 验证码
key = 'VerifyCode-%s' % phonenum # 手机号前加前缀,表示这个手机号功能。
cache.set(key, vcode)
...
return response
现在考虑如何设置验证码过期,比如60秒后验证码失效,
小功能:ipython中可以输入cache.set?会输出参数
输入两个问号会输出源代码cache.set??
可以使用缓存的过期时间来让验证码过期。将上面代码cache.set行修改如下
cache.set(key, vcode,60)
附加面试小课堂:
nginx
静态文件处理,也可以代理动态文件,动静分离的目的
反向代理,不让用户知道服务器。
负载均衡:将任务均匀分发给上百台服务器
uWSGI:协议转化,提升性能,内部集合了一些协程,使用C语言写的。
gunicorn:某些方面比uWSGI好。
nonlocal
global 全局变量
a = 123
def foo(x):
a=a+x
return a
foo(321)
上面会报错,python作用域。修改如下:
a = 123
def foo(x):
global a
a=a+x
return a
foo(321)
def foo():
x = 123
def bar(y):
x = x+y
return x
return bar
返回一个函数bar,bar = foo(321)
还是会报上面同样的错误,这里不能使用global,因为x不是全局变量,但是可以使用nonlocal告诉函数这个x是非本层次的x,但还是局部变量。
def foo():
x = 123
def bar(y):
nonlocal x
x = x+y
return x
return bar
bar = foo()
bar(321)
在ipython 中定义一个数字后
b = 123
b.按table会出现方法属性
一个函数后可以比如加点和下划线按table会出现方法属性。
bar._
bar.closure[0] 这就是闭包,函数和变量打包在一起存在的。
装饰器底层也是一种闭包,装饰完的函数就是闭包。
比如装饰器装饰了函数bar,
使用bar.__name__可以看到它的名字叫wrap
上一篇: Java web项目部署到阿里云服务器上