WEB后端服务第18天-Django第八天

WEB后端服务第18天-Django第8天

一、Django缓存进阶

Django中提供了六种常见缓存策略:

  • 开发调试
  • 内存
  • 文件
  • 数据库
  • Memcache缓存(python-memcached模块)
  • Memcache缓存(pylibmc模块)

1.1 页面缓存

  • @cache_page方案
@cache_page(timeout=10,
            cache='html',
            key_prefix='page')
def list(request):
    # 验证是否登录
    chrs = string.ascii_letters
    char = random.choice(chrs)
    return HttpResponse('用户列表页面: <br> %s' % char)
  • cache.set/add() 保存html

    在中间件的process_request和process_response()两个勾子函数中实现页面缓存。

class CachePageMiddleware(MiddlewareMixin):
    # 配置缓存的页面路径
    cache_page_path = [
        '/user/list/'
    ]

    def process_request(self, request):
        # 判断当前的请求是否支持缓存
        if request.path in self.cache_page_path:

            # 判断页面是否已缓存
            if cache.has_key(request.path):
                return HttpResponse(cache.get(request.path))

    def process_response(self, request, response):
        # 判断当前请求路径是否要被缓存
        if request.path in self.cache_page_path:
            # 开始缓存
            cache.set(request.path,
                      response.content, timeout=5)

        return response

1.2 Redis缓存配置

# 配置缓存Cache
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/10',  # redis://:password@host:port/db
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'SOCKET_CONNECT_TIMEOUT': 10,	# 默认300秒
            'SOCKET_TIMEOUT': 10	# 默认300秒
        }
    }
}

1.3 Session缓存

# 配置SESSION
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_COOKIE_NAME = 'SESSION_ID'	# 默认 sessionid
SESSION_COOKIE_PATH = '/'	
SESSION_CACHE_ALIAS = 'default'		# CACHES配置的的方案名称
SESSION_COOKIE_AGE = 1209600   # 2周有效时间

二、Django信号机制

2.1 信号的优点

  • 监控Django的内部事件
  • 复杂业务之间解耦

2.2 接收内置的信号

  • 普通的接收信号,使用信号对象的connect()函数, 如:
from django.db.models.signals import pre_delete

# 声明信号处理的函数
def model_delete_pre(sender, **kwargs):
    from user.models import Order
    if sender == Order:
        print(info % ('订单模型',
                      kwargs.get('instance').id,
                      kwargs.get('instance').title))

# 接收信号
pre_delete.connect(model_delete_pre)

【注意】信号处理函数的参数声明一般是固定的,**kwargs是一种简单的写法,也可以写成关键参数形式,但不灵活。

  • 支持装饰器的方式接收信号与连接信息处理函数, 如
from django.dispatch import receiver

@receiver(post_delete)
def delete_model_post(sender, **kwargs):
    print(sender, '删除成功', kwargs)

pre_delete.connect(model_delete_pre)

2.3 自定义信号

  • 创建信号

在项目下创建signals包,并在__init__.py脚本中声明信号

from django import dispatch


# 定义信号
# providing_args 声明发送信息的参数列表
codeSignal = dispatch.Signal(providing_args=['path',
                                             'phone',
                                             'code'])
  • 发送信号

    根据业务的需求,在适当的位置上发送信号

def new_code(request):
    # 生成手机验证码
    # 随机产生验证码 : 大小写字母+数字
    code_txt = code.new_code_str(4)
    print(code_txt)

    phone = request.GET.get('phone', '')
    print(phone)

    # 发送信号
    #  sender 名字可以根据需求设定
    #  关键参数列表,根据信号定义的参数列表传值
    signals.codeSignal.send('new_code',
                            path=request.path,
                            phone=phone,
                            code=code_txt)
                            
    return HttpResponse('已向 %s 手机发送了验证码!' % phone)
  • 接收信号

    可以在app模块的__init__.py脚本中接收特定的信号。

from signals import codeSignal
from django import dispatch


# 接收信号
@dispatch.receiver(codeSignal)
def cache_code(sender, **kwargs):
    print('dispatch.receiver<codeSignal>')
    print(sender, kwargs)

中午默写

1. 写出HttpResponse的子类(至少三个)

JsonResponse
HttpResponseRedirect
HttpResponseNotAllowed
HttpResponseGone

2. 写出django的中间件的相关函数

process_request()
process_view()
process_exception()
process_template_response()
process_response()

3. 分页器中Page有哪些属性

number 
object_list
has_previous
has_next
previous_page_number
next_page_number

三、高并发解决方案Celery+Redis队列

3.1 概念

Celery解决C10K问题, 通过消息中间件和后台的任务执行单元解决高并发问题。

Celery的组成部分:

  • 消息中间件 Broker, Celery本身并没有实现功能,只是一种接口或规范,在Celery时,必须指定消息中间件实现方案(Redis 发布/订阅、RabbitMQ )
  • 任务执行单元 Worker, 后台进程
  • 任务执行单元的结果存储 Result

3.2 配置

文档: http://docs.celeryproject.org/en/latest/django/index.html

注意: Window 在Celery4.0之后,不支持多进程方式,更换成协程方式(eventlet, gevent)

安装库

pip install celery==4.4.0rc3 eventlet

在主项目的目录下,创建celery.py, 内容:

from __feture__ import absolute_path, unicode_literals
import os

from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'advanceDjango.settings')

app = Celery('advanceDjango', broker='redis://127.0.0.1:6379/8')
app.config_from_object('django.conf:settings')  # 配置Celery, 加载settings.py

app.autodiscover_tasks()  # 自动发现task任务

在主项目的__init__.py脚本中,增加__all__属性

from __future__ import absolute_import, unicode_literals

from .celery import app as celery_app

# 向项目模块中增加celery_app对象
__all__ = ('celery_app',)

在app应用模块中,创建tasks.py文件

from celery import shared_task

@shared_task
def qbuy(goods_id, user_id):
	  print('goods_id: %s -> user_id: %s' % (goods_id, user_id))
	  return 'goods_id: %s -> user_id: %s' % (goods_id, user_id)

在主项目的settings.py文件, 配置Celery的选项

CELERY_IMPORTS = ('stockapp.tasks',)

启动Celery

> celery -A advanceDjango worker -P eventlet -l info

-P 指定执行单元的实现方式, 指定eventlet 表示以协程方式实现后台执行单元的异步操作。

调用异步任务, @shared_task修改的任务函数

qbuy.delay('10009', 2)

如果Celery服务接收任务,并执行,可以看到执行的结果,但是结果发出的警告。因为没有处理执行单元完成任务的结果。

存储任务结果

  • 存储到redis
app = Celery('advanceDjango', 
					   broker='redis://127.0.0.1:6379/8',
					   backend='redis://127.0.0.1:6379/7')

在创建时,指定Celery()的backend参数,指定results存储到redis中.

  • django-celery-results

安装 存储任务执行结果库

pip install django-celery-results

在settings.py文件中,配置result存储方案

INSTALLED_APPS = [
'...', 
'django_celery_results'
]

CELERY_RESULT_BACKEND = 'django-db'
# CELERY_CACHE_BACKEND = 'django-cache'  # 缓存信息

迁移Celery结果相关的库

> python manage.py migrate django_celery_results

迁移成功之后,重新启动Celery。

调试任务

async_result = qbuy.delay('10009', 2)
async_result.ready()  # 返回False或True, True表示结果已就绪
async_result.result  # 查看任务结果 

3.3 抢购的实现

涉及的技术点: ajax请求, redis的hash, cache使用

3.4 Celery其它配置

格式化:


时区:


scheduler 计划任务

文档: http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html

pip install django-celery-beat
INSTALLED_APPS = [
    ...
    'django_celery_results',
    'django_celery_beat',
]
> python manage.py migrate django_celery_beat
CELERY_TIMEZONE = TIME_ZONE

# 配置计划任务调度类
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers.DatabaseScheduler'

CELERY_BEAT_SCHEDULE = {
    u'定时同步数据2': {
        'task': 'stockapp.tasks.con_data',
        'schedule': 1,
        'args': ('同步oracle', )
    }
}
@shared_task
def con_data(content):
    print('开始同步数据: %s' % content)
    logging.getLogger('').info('开始同步数据: %s' % content)
    return '同步完成'
> celery -A advanceDjango worker -B -l info -f celery.log

注意:window 中不能使用 -B

四、富文本方案

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值