当前位置:   article > 正文

Django开发——缓存机制_django patch_vary_headers

django patch_vary_headers

动态网站的问题就在于它时动态的。也就是说每次用户访问一个页面,服务器要执行数据库查询,启动模板,执行业务逻辑以及最终生成一个你所看到的网页,这一切都是动态即时生成的,从处理资源的角度来看这样是比较昂贵的。
对于与大多数网络应用来说,过载并不是大问题。但对于中等至大规模流量的站点来说,尽可能地解决过载问题时非常必要的。
缓存的目的是为了避免重复计算,特别是对一些比较消耗时间、资源的计算。

设定缓存

必须告诉缓存数据应该放在哪里,在数据库,文件系统或直接在内存中,这将影响你的高速缓存性能。
缓存设置在settings文件中的CACHE_BACKEND中。
内存缓冲
Memcached是迄今为止可用于Django得最快,最有效的缓存类型,Memcached是基于内存的缓存框架。它作为一个守护进程运行,并分配了特定数量的内存。它只是提供了添加,检索和删除缓存中任意数据地高速接口。
在安装了Memcached本身之后,还需要安装Memcached Python绑定,它没有和Django直接绑定。

  • 最快可用选项是一个模块,称为cmemcache
  • 如果无法安装上面的模块,可以安装python-Memcached。
    若要使用Memcached的Django,设置CACHE_BACKEND到memcached://IP:port/,其中IP是Memcached的守护进程的IP地址,port是运行的端口。
    例如在本机运行:
CACHE_BACKEND='memcached://127.0.0.1:11211IP
  • 1

Memcached的一个极好的特性是它在多个服务器间分享缓存能力,该程序会把这些机器当成一个单一缓存,而无需重复每台机器上的缓存值。如果想使用这个功能。在CACHE_BACKEND里引入所有服务器的地址,用分号分隔。

CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11211/'
  • 1

**缺点:**由于缓存的数据在内存中,如果服务器崩溃,数据将消失。所以不要把基于内存的缓存当作唯一的存储数据缓存。
数据库缓存
创建缓存表

python manage.py createcachetable [数据表名]
  • 1

创建了数据库表,把你的CACHE_BACKEND设置为“db://tablename”,这里的tablename是数据库表的名字。

CACHE_BACKEND='db://my_cache_table'
  • 1

数据库缓存后端使用你的settings文件指定的同一个数据库。

文件系统缓存

CACHE_BACKEND = 'file:///var/tmp/django_cache'
  • 1

头两个//是file://,第三项是目录路径/var/tmp/django_cache
确认该设置指向的目录存在并且你的Web服务器运行的系统的用户可以读写该目录。每个缓存值将被存储为单独的文件,其内容是python的pickle模块以序列化形式保存的缓存数据。每个文件名称是缓存键,以规避开安全文件系统的使用。
本地内存缓存
如果想使用内存缓存但又不想使用Memcached,可以考虑本地缓存后端。此缓存得多进程和线程安全。

CACHE_BACKEND='locmen:///'
  • 1

每个进程都有自己私有的缓存实例,所以跨进程是不可能的,所以效率不太高,不适用于产品。
仿缓存
供开发时使用

CACHE_BACKEND='dummy:///'
  • 1

使用自定义缓存后端
让Django使用外部缓存后端

CACHE_BACKEND='path.to.backend://'
  • 1

最好使用Django包含的缓存后端
CACHE_BACKEND参数

参数描述
timeout用于缓存的过期时间,以秒为单位,默认为300秒
max_entries高速缓存允许的最大条目数,超出这个数则旧值将被删除,默认为300
cull_percentage当达到max_entries时被删除的条目比率。
cull_frequency当设置为0时达到max_entries时缓存将被清空
CACHE_BACKEND = "memcached://127.0.0.1:11211/?timeout=60"
  • 1
CACHE_BACKEND = "locmem:///?timeout=30&max_entries=400"
  • 1

站点级Cache

一旦高速缓存设置,最简单的方法是时用缓存缓存整个网站。配置如下:

MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
]
  • 1
  • 2
  • 3
  • 4
  • 5
  • CACHE_MIDDLEWARE_SECONDS :每个页面应该被缓存的秒数
  • CACHE_MIDDLEWARE_KEY_PREFIX :如果缓存被多个使用相同Django安装的网站所共享,那么把这个值设成当前网站名,或其他能代表这个Django实例的唯一字符串,以避key发生冲突。 如果你不在意的话可以设成空字符串。
  • CACHE_MIDDLEWARE_ANONYMOUS_ONLY设置为True,只有匿名请求(即不是由登录的用户)将被缓存。

视图级缓存

django.views.decorators.cache定义了一个自动缓存视图响应的cache_page装饰器。

from django.views.decorators.cache import cache_page

def my_view(request):
    pass

my_view=cache_page(my_view,60*15)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

和站点一样,视图缓存与URL无关,如果多个URL指向同一视图,每个视图将会分别缓存。

urlpatterns = [
    url(r'^/foo/(\d{1,2})$',my_view),
    ]
  • 1
  • 2
  • 3

这样,发送到/foo/1/的请求将会被分别缓存,单一旦发出特定的请求值后再度法送出的指向URL的请求将会时用缓存。
直接在URLconf中指定缓存

urlpatterns = [
    url(r'^/foo/(\d{1,2})$',cache_page(my_view)),
    ]
  • 1
  • 2
  • 3

模板碎片缓存

也可以使用cache标签来缓存模板片段,在模板的顶端加入附近{% load cache %}以统治模板存取缓存标签。

{% load cache %}
{% cache 500 sidebar %}
	'''
{% endcache %}
  • 1
  • 2
  • 3
  • 4

基于片段的动态内容的多份拷贝。比如想给每个用户分别缓存侧边栏。给{% cache %}传入额外的参数以标识缓存片段。

{% load cache %}
{% cache 500 sidebar request.user.username %}
	'''
{% endcache %}
  • 1
  • 2
  • 3
  • 4

缓存超时时间可以作为模板变量,只要它可以解析为整数值。

{% cache 600 sidebar %} ... {% endcache %}
{% cache my_timeout sidebar %} ... {% endcache %}
  • 1
  • 2

低层次缓存API

如果你不想解析整个页面,而是对很少变化的部分进行缓存,Django日宫了简单的缓存API,以任何你需要的粒度来缓存对象。可以对所有能都安全进行pikcle处理的Python对象进行缓存。
缓存模块django.core.cache拥有一个自动依据CACHE_BACKEND设置创建的django.core.cache对象。

>>> from django.core.cache import cache
>>> cache.set('my_key','hello',30)
>>> cache.get('my_key')
'hello'
  • 1
  • 2
  • 3
  • 4

如果过期,缓存中就不存在该对象,那么将会返回空。

>>> cache.get('my_key')
>>> 
  • 1
  • 2

bu==部件以才缓存中保存None常量,因为无法区别你保存的None变量及由返回值None所标识的缓存未命中。
cache.get()机一首一个缺省的参数。它指定了当缓存中不存在该对象时所返回的值:

>>> cache.get('my_key','has expired')
'has expired'

  • 1
  • 2
  • 3

使用add()方法来新增一个原来没有的键值。它接受的参数和set一样,但并不更新。

>>> cache.set('add_key','Initial value')
>>> cache.add('add_key','New value')
False
>>> cache.get('add_key')
'Initial value'

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

如果返回False表示失败。
get_many()接口,返回的字典包括了你所请求的存在于缓存中且未超时的所有键值。

>>> cache.set('a',300)
>>> cache.set('b',300)
>>> cache.set('c',300)
>>> cache.get_many(['a','b','c'])
{'a': 300, 'b': 300, 'c': 300}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

可以使用cache.delete()显式的删除关键字

>>> cache.delete('a')
>>> cache.get_many(['a','b','c'])
{'b': 300, 'c': 300}
  • 1
  • 2
  • 3

增加或减少已经存在的键值。

>>> cache.set('num',1)
>>> cache.incr('num')
2
>>> cache.incr('num',10)
12
>>> cache.decr('num',10)
2
>>> cache.decr('num',5)
-3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

使用Vary头部

Vary头部定义了缓存机制在构建其缓存键值时应当将哪个请求头标考虑在内。
缺省情况下,Django的缓存系统使用请求的路径来创建其缓存健。

@vary_on_headers('User-Agent')
def my_view(request):
    pass
  • 1
  • 2
  • 3

这种缓存机制将会为每个单独用户浏览器缓存一个独立的页面版本。
使用vary_on_headers装饰器而不是手动设置Vary头部的好处时修饰器在Vary之上添加,而不是从零开始设置。

@vary_on_headers('User-Agent','Cookie')
def my_view(request):
    pass
  • 1
  • 2
  • 3

传入多个头标,通知上游缓存对两者都进行不同操作,user_agent和cookie得每种组合都应获取自己的缓存值。
根据cookie而符区分对待是常见的情况,因此有vary_on _cookie装饰器。
也可以直接使用帮助函数django.utils.cache.patch_vary_headers。该函数设置或增加Vary header

from django.utils.cache import patch_vary_headers


def my_view(request):
    
    response=render_to_response('template_name',context)
    patch_vary_headers(response,['Cookie'])
    return response
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

控制缓存:使用其他头部

用户将会面对两种缓存,一个是自己的浏览器缓存,另一个是提供者缓存。由与公共缓存由多个用户使用,所以存在安全问题。
解决方案时符告诉缓存哪些是共有的哪些是私有的。

from django.views.decorators.cache import cache_control
@cache_control(private=True)
def my_view
  • 1
  • 2
  • 3

该装饰器负责在后台发送相应的HTTP头部。
cache_control 告诉缓存对
每次访问都重新验证缓存并在最长 3600 秒内保存所缓存版本:

from django.views.decorators.cache import cache_control
@cache_control(must_revalidate=True, max_age=3600)
def my_view(request):
# ...
  • 1
  • 2
  • 3
  • 4

在 cache_control() 中,任何合法的 Cache‐Control HTTP 指令都是有效的。下面是完整列表:
public=True
private=True
no_cache=True
no_transform=True
must_revalidate=True
proxy_revalidate=True
max_age=num_seconds
s_maxage=num_seconds
如果你在cache_control
修饰器中使用了自定义的max_age,该修饰器将会取得优先权,该头部的值将被正确地被合并。如果你想用头部完全禁掉缓存, django.views.decorators.cache.never_cache 装饰器可以添加确保响应不被缓存的头部信息。

from django.views.decorators.cache import never_cache
@never_cache
def myview(
  • 1
  • 2
  • 3
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/259033
推荐阅读
相关标签
  

闽ICP备14008679号