日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

中國最全I(xiàn)T社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2

django教程

Django 緩存機(jī)制

閱讀 (2190)

動態(tài)網(wǎng)站的問題就在于它是動態(tài)的。 也就是說每次用戶訪問一個頁面,服務(wù)器要執(zhí)行數(shù)據(jù)庫查詢,啟動模板,執(zhí)行業(yè)務(wù)邏輯以及最終生成一個你所看到的網(wǎng)頁,這一切都是動態(tài)即時生成的。 從處理器資源的角度來看,這是比較昂貴的。

對于大多數(shù)網(wǎng)絡(luò)應(yīng)用來說,過載并不是大問題。 因?yàn)榇蠖鄶?shù)網(wǎng)絡(luò)應(yīng)用并不是washingtonpost.com或Slashdot;它們通常是很小很簡單,或者是中等規(guī)模的站點(diǎn),只有很少的流量。 但是對于中等至大規(guī)模流量的站點(diǎn)來說,盡可能地解決過載問題是非常必要的。

這就需要用到緩存了。

緩存的目的是為了避免重復(fù)計(jì)算,特別是對一些比較耗時間、資源的計(jì)算。 下面的偽代碼演示了如何對動態(tài)頁面的結(jié)果進(jìn)行緩存。

given a URL, try finding that page in the cache
if the page is in the cache:
    return the cached page
else:
    generate the page
    save the generated page in the cache (for next time)
    return the generated page

為此,Django提供了一個穩(wěn)定的緩存系統(tǒng)讓你緩存動態(tài)頁面的結(jié)果,這樣在接下來有相同的請求就可以直接使用緩存中的數(shù)據(jù),避免不必要的重復(fù)計(jì)算。 另外Django還提供了不同粒度數(shù)據(jù)的緩存,例如: 你可以緩存整個頁面,也可以緩存某個部分,甚至緩存整個網(wǎng)站。

Django也和”上游”緩存工作的很好,例如Squid(http://www.squid-cache.org)和基于瀏覽器的緩存。 這些類型的緩存你不直接控制,但是你可以提供關(guān)于你的站點(diǎn)哪部分應(yīng)該被緩存和怎樣緩存的線索(通過HTTP頭部)給它們

設(shè)定緩存

緩存系統(tǒng)需要一些少量的設(shè)定工作。 也就是說,你必須告訴它緩存的數(shù)據(jù)應(yīng)該放在哪里,在數(shù)據(jù)庫中,在文件系統(tǒng),或直接在內(nèi)存中。 這是一個重要的決定,影響您的高速緩存的性能,是的,有些類型的緩存比其它類型快。

緩存設(shè)置在settings文件的 CACHE_BACKEND中。 這里是一個CACHE_BACKEND所有可用值的解釋。

內(nèi)存緩沖

Memcached是迄今為止可用于Django的最快,最有效的緩存類型,Memcached是完全基于內(nèi)存的緩存框架,最初開發(fā)它是用以處理高負(fù)荷的LiveJournal.com隨后由Danga Interactive公司開源。 它被用于一些站點(diǎn),例如Facebook和維基百科網(wǎng)站,以減少數(shù)據(jù)庫訪問,并大幅提高站點(diǎn)的性能。

Memcached是免費(fèi)的(http://danga.com/memcached)。它作為一個守護(hù)進(jìn)程運(yùn)行,并分配了特定數(shù)量的內(nèi)存。 它只是提供了添加,檢索和刪除緩存中的任意數(shù)據(jù)的高速接口。 所有數(shù)據(jù)都直接存儲在內(nèi)存中,所以沒有對使用的數(shù)據(jù)庫或文件系統(tǒng)的開銷。

在安裝了Memcached本身之后,你將需要安裝Memcached Python綁定,它沒有直接和Django綁定。 這兩個可用版本。 選擇和安裝以下模塊之一:

  • 最快的可用選項(xiàng)是一個模塊,稱為cmemcache,在http://gijsbert.org/cmemcache。

  • 如果您無法安裝cmemcache,您可以安裝python - Memcached,在ftp://ftp.tummy.com/pub/python-memcached/。如果該網(wǎng)址已不再有效,只要到Memcached的網(wǎng)站http://www.danga.com/memcached/),并從客戶端API完成Python綁定。

若要使用Memcached的Django,設(shè)置CACHE_BACKEND到memcached:/ / IP:port/,其中IP是Memcached的守護(hù)進(jìn)程的IP地址,port是Memcached運(yùn)行的端口。

在這個例子中,Memcached運(yùn)行在本地主機(jī) (127.0.0.1)上,端口為11211:

CACHE_BACKEND = 'memcached://127.0.0.1:11211/'

Memcached的一個極好的特性是它在多個服務(wù)器間分享緩存的能力。 這意味著您可以在多臺機(jī)器上運(yùn)行Memcached的守護(hù)進(jìn)程,該程序會把這些機(jī)器當(dāng)成一個單一緩存,而無需重復(fù)每臺機(jī)器上的緩存值。 要充分利用此功能,請?jiān)贑ACHE_BACKEND里引入所有服務(wù)器的地址,用分號分隔。

這個例子中,緩存在運(yùn)行在IP地址為172.19.26.240和172.19.26.242,端口號為11211的Memcached實(shí)例間分享:

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

這個例子中,緩存在運(yùn)行在172.19.26.240(端口11211),172.19.26.242(端口11212),172.19.26.244(端口11213)的Memcached實(shí)例間分享:

CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11212;172.19.26.244:11213/'

最后有關(guān)Memcached的一點(diǎn)是,基于內(nèi)存的緩存有一個重大的缺點(diǎn)。 由于緩存的數(shù)據(jù)存儲在內(nèi)存中,所以如果您的服務(wù)器崩潰,數(shù)據(jù)將會消失。 顯然,內(nèi)存不是用來持久化數(shù)據(jù)的,因此不要把基于內(nèi)存的緩存作為您唯一的存儲數(shù)據(jù)緩存。 毫無疑問,在Django的緩存后端不應(yīng)該用于持久化,它們本來就被設(shè)計(jì)成緩存的解決方案。但我們?nèi)匀恢赋龃它c(diǎn),這里是因?yàn)榛趦?nèi)存的緩存是暫時的。

數(shù)據(jù)庫緩存

為了使用數(shù)據(jù)庫表作為緩存后端,首先在數(shù)據(jù)庫中運(yùn)行這個命令以創(chuàng)建緩存表:

python manage.py createcachetable [cache_table_name]

這里的[cache_table_name]是要創(chuàng)建的數(shù)據(jù)庫表名。 (這個名字隨你的便,只要它是一個有效的表名,而且不是已經(jīng)在您的數(shù)據(jù)庫中使用的表名。)這個命令以Django的數(shù)據(jù)庫緩存系統(tǒng)所期望的格式創(chuàng)建一個表。

一旦你創(chuàng)建了數(shù)據(jù)庫表,把你的CACHE_BACKEND設(shè)置為”db://tablename”,這里的tablename是數(shù)據(jù)庫表的名字,在這個例子中,緩存表名為my_cache_table: 在這個例子中,高速緩存表的名字是my_cache_table:

CACHE_BACKEND = 'db://my_cache_table'

數(shù)據(jù)庫緩存后端使用你的settings文件指定的同一數(shù)據(jù)庫。 你不能為你的緩存表使用不同的數(shù)據(jù)庫后端.

如果你已經(jīng)有了一個快速,良好的索引數(shù)據(jù)庫服務(wù)器,那么數(shù)據(jù)庫緩存的效果最明顯。

文件系統(tǒng)緩存

要把緩存項(xiàng)目放在文件系統(tǒng)上,請為CACHE_BACKEND使用”file://“的緩存類型。例如,要把緩存數(shù)據(jù)存儲在/var/tmp/django_cache上,請使用此設(shè)置:

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

注意例子中開頭有三個斜線。 頭兩項(xiàng)是file://,第三個是第一個字符的目錄路徑,/var/tmp/django_cache。如果你使用的是Windows,在file://之后加上文件的驅(qū)動器號:

file://c:/foo/bar

目錄路徑應(yīng)該是絕對路徑,即應(yīng)該以你的文件系統(tǒng)的根開始。 在設(shè)置的結(jié)尾放置斜線與否無關(guān)緊要。

確認(rèn)該設(shè)置指向的目錄存在并且你的Web服務(wù)器運(yùn)行的系統(tǒng)的用戶可以讀寫該目錄。 繼續(xù)上面的例子,如果你的服務(wù)器以用戶apache運(yùn)行,確認(rèn)/var/tmp/django_cache存在并且用戶apache可以讀寫/var/tmp/django_cache目錄。

每個緩存值將被存儲為單獨(dú)的文件,其內(nèi)容是Python的pickle模塊以序列化(“pickled”)形式保存的緩存數(shù)據(jù)。 每個文件的名稱是緩存鍵,以規(guī)避開安全文件系統(tǒng)的使用。

本地內(nèi)存緩存

如果你想利用內(nèi)存緩存的速度優(yōu)勢,但又不能使用Memcached,可以考慮使用本地存儲器緩存后端。 此緩存的多進(jìn)程和線程安全。 設(shè)置 CACHE_BACKEND 為 locmem:/// 來使用它,例如:

CACHE_BACKEND = 'locmem:///'

請注意,每個進(jìn)程都有自己私有的緩存實(shí)例,這意味著跨進(jìn)程緩存是不可能的。 這顯然也意味著本地內(nèi)存緩存效率并不是特別高,所以對產(chǎn)品環(huán)境來說它可能不是一個好選擇。 對開發(fā)來說還不錯。

仿緩存(供開發(fā)時使用)

最后,Django提供了一個假緩存(只是實(shí)現(xiàn)了緩存接口,實(shí)際上什么都不做)。

假如你有一個產(chǎn)品站點(diǎn),在許多地方使用高度緩存,但在開發(fā)/測試環(huán)境中,你不想緩存,也不想改變代碼,這就非常有用了。 要激活虛擬緩存,就像這樣設(shè)置CACHE_BACKEND:

CACHE_BACKEND = 'dummy:///'

使用自定義緩存后端

盡管Django包含對許多緩存后端的支持,在某些情況下,你仍然想使用自定義緩存后端。 要讓Django使用外部緩存后端,需要使用一個Python import路徑作為的CACHE_BACKEND URI的(第一個冒號前的部分),像這樣:

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

如果您構(gòu)建自己的后端,你可以參考標(biāo)準(zhǔn)緩存后端的實(shí)現(xiàn)。 源代碼在Django的代碼目錄的django/core/cache/backends/下。

注意 如果沒有一個真正令人信服的理由,比如主機(jī)不支持,你就應(yīng)該堅(jiān)持使用Django包含的緩存后端。 它們經(jīng)過大量測試,并且易于使用。

CACHE_BACKEND參數(shù)

每個緩存后端都可能使用參數(shù)。 它們在CACHE_BACKEND設(shè)置中以查詢字符串形式給出。 有效參數(shù)如下:

timeout:用于緩存的過期時間,以秒為單位。 這個參數(shù)默認(rèn)被設(shè)置為300秒(五分鐘)。

max_entries:對于內(nèi)存,文件系統(tǒng)和數(shù)據(jù)庫后端,高速緩存允許的最大條目數(shù),超出這個數(shù)則舊值將被刪除。 這個參數(shù)默認(rèn)是300。

cull_percentage :當(dāng)達(dá)到 max_entries 的時候,被刪除的條目比率。 實(shí)際的比率是 1/cull_percentage ,所以設(shè)置cull_frequency=2就是在達(dá)到 max_entries 的時候去除一半數(shù)量的緩存。

把 cull_frequency 的值設(shè)置為 0 意味著當(dāng)達(dá)到 max_entries 時,緩存將被清空。 這將以很多緩存丟失為代價,大大提高接受訪問的速度。

在這個例子中, timeout 被設(shè)成 60

CACHE_BACKEND = "memcached://127.0.0.1:11211/?timeout=60"

而在這個例子中, timeout 設(shè)為 30 而 max_entries 為 400 :

CACHE_BACKEND = "locmem:///?timeout=30&max_entries=400"

其中,非法的參數(shù)與非法的參數(shù)值都將被忽略。

站點(diǎn)級 Cache

一旦高速緩存設(shè)置,最簡單的方法是使用緩存緩存整個網(wǎng)站。 您 需要添加’django.middleware.cache.UpdateCacheMiddleware’和 ‘django.middleware.cache.FetchFromCacheMiddleware’到您的MIDDLEWARE_CLASSES設(shè)置中,在這個例子中是:

MIDDLEWARE_CLASSES = (
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
)

注意:

不,這里并沒有排版錯誤: 修改的中間件,必須放在列表的開始位置,而fectch中間件,必須放在最后。 細(xì)節(jié)有點(diǎn)費(fèi)解,如果您想了解完整內(nèi)幕請參看下面的MIDDLEWARE_CLASSES順序。

然后,在你的Django settings文件里加入下面所需的設(shè)置:

  • CACHE_MIDDLEWARE_SECONDS :每個頁面應(yīng)該被緩存的秒數(shù)。

  • CACHE_MIDDLEWARE_KEY_PREFIX :如果緩存被多個使用相同Django安裝的網(wǎng)站所共享,那么把這個值設(shè)成當(dāng)前網(wǎng)站名,或其他能代表這個Django實(shí)例的唯一字符串,以避免key發(fā)生沖突。 如果你不在意的話可以設(shè)成空字符串。

緩存中間件緩存每個沒有GET或者POST參數(shù)的頁面。 或者,如果CACHE_MIDDLEWARE_ANONYMOUS_ONLY設(shè)置為True,只有匿名請求(即不是由登錄的用戶)將被緩存。 如果想取消用戶相關(guān)頁面(user-specific pages)的緩存,例如Djangos 的管理界面,這是一種既簡單又有效的方法。 CACHE_MIDDLEWARE_ANONYMOUS_ONLY,你應(yīng)該確保你已經(jīng)啟動AuthenticationMiddleware。

此外,緩存中間件為每個HttpResponse自動設(shè)置了幾個頭部信息:

  • 當(dāng)一個新(沒緩存的)版本的頁面被請求時設(shè)置Last-Modified頭部為當(dāng)前日期/時間。

  • 設(shè)置Expires頭部為當(dāng)前日期/時間加上定義的CACHE_MIDDLEWARE_SECONDS。

  • 設(shè)置Cache-Control頭部來給頁面一個最長的有效期,值來自于CACHE_MIDDLEWARE_SECONDS設(shè)置。

參閱更多的中間件第17章。

如果視圖設(shè)置自己的緩存到期時間(即 它有一個最大年齡在頭部信息的Cache-Control中),那么頁面將緩存直到過期,而不是CACHE_MIDDLEWARE_SECONDS。使用django.views.decorators.cache裝飾器,您可以輕松地設(shè)置視圖的到期時間(使用cache_control裝飾器)或禁用緩存視圖(使用never_cache裝飾器)。 請參閱下面的”使用其他頭部信息“小節(jié)以了解裝飾器的更多信息。

視圖級緩存

更加顆粒級的緩存框架使用方法是對單個視圖的輸出進(jìn)行緩存。 django.views.decorators.cache定義了一個自動緩存視圖響應(yīng)的cache_page裝飾器。 他是很容易使用的:

from django.views.decorators.cache import cache_page

def my_view(request):
    # ...

my_view = cache_page(my_view, 60 * 15)

也可以使用Python2.4的裝飾器語法:

@cache_page(60 * 15)
def my_view(request):
    # ...

cache_page 只接受一個參數(shù): 以秒計(jì)的緩存超時時間。 在前例中, “my_view()” 視圖的結(jié)果將被緩存 15 分鐘。 (注意: 為了提高可讀性,該參數(shù)被書寫為 60  15 。 60  15 將被計(jì)算為 900 ,也就是說15 分鐘乘以每分鐘 60 秒。)

和站點(diǎn)緩存一樣,視圖緩存與 URL 無關(guān)。 如果多個 URL 指向同一視圖,每個視圖將會分別緩存。 繼續(xù)my_view 范例,如果 URLconf 如下所示:

urlpatterns = ('',
    (r'^foo/(\d{1,2})/$', my_view),
)

那么正如你所期待的那樣,發(fā)送到 /foo/1/ 和 /foo/23/ 的請求將會分別緩存。 但一旦發(fā)出了特定的請求(如: /foo/23/ ),之后再度發(fā)出的指向該 URL 的請求將使用緩存。

在 URLconf 中指定視圖緩存

前一節(jié)中的范例將視圖硬編碼為使用緩存,因?yàn)?nbsp;cache_page 在適當(dāng)?shù)奈恢脤?nbsp;my_view 函數(shù)進(jìn)行了轉(zhuǎn)換。 該方法將視圖與緩存系統(tǒng)進(jìn)行了耦合,從幾個方面來說并不理想。 例如,你可能想在某個無緩存的站點(diǎn)中重用該視圖函數(shù),或者你可能想將該視圖發(fā)布給那些不想通過緩存使用它們的人。 解決這些問題的方法是在 URLconf 中指定視圖緩存,而不是緊挨著這些視圖函數(shù)本身來指定。

完成這項(xiàng)工作非常簡單: 在 URLconf 中用到這些視圖函數(shù)的時候簡單地包裹一個 cache_page 。以下是剛才用到過的 URLconf : 這是之前的URLconf:

urlpatterns = ('',
    (r'^foo/(\d{1,2})/$', my_view),
)

以下是同一個 URLconf ,不過用 cache_page 包裹了 my_view :

from django.views.decorators.cache import cache_page

urlpatterns = ('',
    (r'^foo/(\d{1,2})/$', cache_page(my_view, 60 * 15)),
)

如果采取這種方法, 不要忘記在 URLconf 中導(dǎo)入 cache_page。

模板碎片緩存

你同樣可以使用cache標(biāo)簽來緩存模板片段。 在模板的頂端附近加入{% load cache %}以通知模板存取緩存標(biāo)簽。

模板標(biāo)簽{% cache %}在給定的時間內(nèi)緩存了塊的內(nèi)容。 它至少需要兩個參數(shù): 緩存超時時間(以秒計(jì))和指定緩存片段的名稱。 示例:

{% load cache %}
{% cache 500 sidebar %}
    .. sidebar ..
{% endcache %}

有時你可能想緩存基于片段的動態(tài)內(nèi)容的多份拷貝。 比如,你想為上一個例子的每個用戶分別緩存?zhèn)冗厵凇?這樣只需要給{% cache %}傳遞額外的參數(shù)以標(biāo)識緩存片段。

{% load cache %}
{% cache 500 sidebar request.user.username %}
    .. sidebar for logged in user ..
{% endcache %}

傳遞不止一個參數(shù)也是可行的。 簡單地把參數(shù)傳給{% cache %}。

緩存超時時間可以作為模板變量,只要它可以解析為整數(shù)值。 例如,如果模板變量my_timeout值為600,那么以下兩個例子是等價的。

{% cache 600 sidebar %} ... {% endcache %}
{% cache my_timeout sidebar %} ... {% endcache %}

這個特性在避免模板重復(fù)方面非常有用。 可以把超時時間保存在變量里,然后在別的地方復(fù)用。

低層次緩存API

有些時候,對整個經(jīng)解析的頁面進(jìn)行緩存并不會給你帶來太多好處,事實(shí)上可能會過猶不及。

比如說,也許你的站點(diǎn)所包含的一個視圖依賴幾個費(fèi)時的查詢,每隔一段時間結(jié)果就會發(fā)生變化。 在這種情況下,使用站點(diǎn)級緩存或者視圖級緩存策略所提供的整頁緩存并不是最理想的,因?yàn)槟憧赡懿粫雽φ麄€結(jié)果進(jìn)行緩存(因?yàn)橐恍?shù)據(jù)經(jīng)常變化),但你仍然會想對很少變化的部分進(jìn)行緩存。

針對這樣的情況,Django提供了簡單低級的緩存API。 你可以通過這個API,以任何你需要的粒度來緩存對象。 你可以對所有能夠安全進(jìn)行 pickle 處理的 Python 對象進(jìn)行緩存: 字符串、字典和模型對象列表等等。 (查閱 Python 文檔可以了解到更多關(guān)于 pickling 的信息。)

緩存模塊django.core.cache擁有一個自動依據(jù)CACHE_BACKEND設(shè)置創(chuàng)建的django.core.cache對象。

>>> from django.core.cache import cache

基本的接口是 set(key, value, timeout_seconds) 和 get(key) :

>>> cache.set('my_key', 'hello, world!', 30)
>>> cache.get('my_key')
'hello, world!'

timeout_seconds 參數(shù)是可選的, 并且默認(rèn)為前面講過的 CACHE_BACKEND 設(shè)置中的 timeout 參數(shù).

如果緩存中不存在該對象,那么cache.get()會返回None。

# Wait 30 seconds for 'my_key' to expire...

>>> cache.get('my_key')
None

我們不建議在緩存中保存 None 常量,因?yàn)槟銓o法區(qū)分你保存的 None 變量及由返回值 None 所標(biāo)識的緩存未命中。

cache.get() 接受一個 缺省 參數(shù)。 它指定了當(dāng)緩存中不存在該對象時所返回的值:

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

使用add()方法來新增一個原來沒有的鍵值。 它接受的參數(shù)和set()一樣,但是并不去嘗試更新已經(jīng)存在的鍵值。

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

如果想確定add()是否成功添加了緩存值,你應(yīng)該測試返回值。 成功返回True,失敗返回False。

還有個get_many()接口。 get_many() 所返回的字典包括了你所請求的存在于緩存中且未超時的所有鍵值。

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

最后,你可以用 cache.delete() 顯式地刪除關(guān)鍵字。

>>> cache.delete('a')

也可以使用incr()或者decr()來增加或者減少已經(jīng)存在的鍵值。 默認(rèn)情況下,增加或減少的值是1??梢杂脜?shù)來制定其他值。 如果嘗試增減不存在的鍵值會拋出ValueError。

>>> cache.set('num', 1)
>>> cache.incr('num')
2
>>> cache.incr('num', 10)
12
>>> cache.decr('num')
11
>>> cache.decr('num', 5)
6

注意

incr()/decr()方法不是原子操作。 在支持原子增減的緩存后端上(最著名的是memcached),增減操作才是原子的。 然而,如果后端并不原生支持增減操作,也可以通過取值/更新兩步操作來實(shí)現(xiàn)。

上游緩存

目前為止,本章的焦點(diǎn)一直是對你 自己的 數(shù)據(jù)進(jìn)行緩存。 但還有一種與 Web 開發(fā)相關(guān)的緩存: 上游緩存。 有一些系統(tǒng)甚至在請求到達(dá)站點(diǎn)之前就為用戶進(jìn)行頁面緩存。

下面是上游緩存的幾個例子:

  • 你的 ISP (互聯(lián)網(wǎng)服務(wù)商)可能會對特定的頁面進(jìn)行緩存,因此如果你向 http://example.com/ 請求一個頁面,你的 ISP 可能無需直接訪問 example.com 就能將頁面發(fā)送給你。 而 example.com 的維護(hù)者們卻無從得知這種緩存,ISP 位于 example.com 和你的網(wǎng)頁瀏覽器之間,透明地處理所有的緩存。

  • 你的 Django 網(wǎng)站可能位于某個 代理緩存 之后,例如 Squid 網(wǎng)頁代理緩存 (http://www.squid-cache.org/),該緩存為提高性能而對頁面進(jìn)行緩存。 在此情況下 ,每個請求將首先由代理服務(wù)器進(jìn)行處理,然后僅在需要的情況下才被傳遞至你的應(yīng)用程序。

  • 你的網(wǎng)頁瀏覽器也對頁面進(jìn)行緩存。 如果某網(wǎng)頁送出了相應(yīng)的頭部,你的瀏覽器將在為對該網(wǎng)頁的后續(xù)的訪問請求使用本地緩存的拷貝,甚至不會再次聯(lián)系該網(wǎng)頁查看是否發(fā)生了變化。

上游緩存將會產(chǎn)生非常明顯的效率提升,但也存在一定風(fēng)險。 許多網(wǎng)頁的內(nèi)容依據(jù)身份驗(yàn)證以及許多其他變量的情況發(fā)生變化,緩存系統(tǒng)僅盲目地根據(jù) URL 保存頁面,可能會向這些頁面的后續(xù)訪問者暴露不正確或者敏感的數(shù)據(jù)。

舉個例子,假定你在使用網(wǎng)頁電郵系統(tǒng),顯然收件箱頁面的內(nèi)容取決于登錄的是哪個用戶。 如果 ISP 盲目地緩存了該站點(diǎn),那么第一個用戶通過該 ISP 登錄之后,他(或她)的用戶收件箱頁面將會緩存給后續(xù)的訪問者。 這一點(diǎn)也不好玩。

幸運(yùn)的是, HTTP 提供了解決該問題的方案。 已有一些 HTTP 頭標(biāo)用于指引上游緩存根據(jù)指定變量來區(qū)分緩存內(nèi)容,并通知緩存機(jī)制不對特定頁面進(jìn)行緩存。 我們將在本節(jié)后續(xù)部分將對這些頭標(biāo)進(jìn)行闡述。

使用 Vary頭部

Vary 頭部定義了緩存機(jī)制在構(gòu)建其緩存鍵值時應(yīng)當(dāng)將哪個請求頭標(biāo)考慮在內(nèi)。 例如,如果網(wǎng)頁的內(nèi)容取決于用戶的語言偏好,該頁面被稱為根據(jù)語言而不同。

缺省情況下,Django 的緩存系統(tǒng)使用所請求的路徑(比如:"/stories/2005/jun/23/bank_robbed/" )來創(chuàng)建其緩存鍵。這意味著每次請求都會使用同樣的緩存版本,不考慮才客戶端cookie和語言配置的不同。 除非你使用Vary頭部通知緩存機(jī)制頁面輸出要依據(jù)請求頭里的cookie,語言等的設(shè)置而不同。

要在 Django 完成這項(xiàng)工作,可使用便利的 vary_on_headers 視圖裝飾器,如下所示:

from django.views.decorators.vary import vary_on_headers

# Python 2.3 syntax.
def my_view(request):
    # ...
my_view = vary_on_headers(my_view, 'User-Agent')

# Python 2.4+ decorator syntax.
@vary_on_headers('User-Agent')
def my_view(request):
    # ...

在這種情況下,緩存機(jī)制(如 Django 自己的緩存中間件)將會為每一個單獨(dú)的用戶瀏覽器緩存一個獨(dú)立的頁面版本。

使用 vary_on_headers 裝飾器而不是手動設(shè)置 Vary 頭部(使用像 response['Vary'] = 'user-agent' 之類的代碼)的好處是修飾器在(可能已經(jīng)存在的) Vary 之上進(jìn)行 添加 ,而不是從零開始設(shè)置,且可能覆蓋該處已經(jīng)存在的設(shè)置。

你可以向 vary_on_headers() 傳入多個頭標(biāo):

@vary_on_headers('User-Agent', 'Cookie')
def my_view(request):
    # ...

該段代碼通知上游緩存對 兩者 都進(jìn)行不同操作,也就是說 user-agent 和 cookie 的每種組合都應(yīng)獲取自己的緩存值。 舉例來說,使用 Mozilla 作為 user-agent 而 foo=bar 作為 cookie 值的請求應(yīng)該和使用 Mozilla 作為 user-agent 而 foo=ham 的請求應(yīng)該被視為不同請求。

由于根據(jù) cookie 而區(qū)分對待是很常見的情況,因此有 vary_on_cookie 裝飾器。 以下兩個視圖是等效的:

@vary_on_cookie
def my_view(request):
    # ...

@vary_on_headers('Cookie')
def my_view(request):
    # ...

傳入 vary_on_headers 頭標(biāo)是大小寫不敏感的; "User-Agent" 與 "user-agent" 完全相同。

你也可以直接使用幫助函數(shù):django.utils.cache.patch_vary_headers。 該函數(shù)設(shè)置或增加 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

patch_vary_headers 以一個 HttpResponse 實(shí)例為第一個參數(shù),以一個大小寫不敏感的頭標(biāo)名稱列表或元組為第二個參數(shù)。

控制緩存: 使用其它頭部

關(guān)于緩存剩下的問題是數(shù)據(jù)的隱私性以及在級聯(lián)緩存中數(shù)據(jù)應(yīng)該在何處儲存的問題。

通常用戶將會面對兩種緩存: 他或她自己的瀏覽器緩存(私有緩存)以及他或她的提供者緩存(公共緩存)。 公共緩存由多個用戶使用,而受其他某人的控制。 這就產(chǎn)生了你不想遇到的敏感數(shù)據(jù)的問題,比如說你的銀行賬號被存儲在公眾緩存中。 因此,Web 應(yīng)用程序需要以某種方式告訴緩存那些數(shù)據(jù)是私有的,哪些是公共的。

解決方案是標(biāo)示出某個頁面緩存應(yīng)當(dāng)是私有的。 要在 Django 中完成此項(xiàng)工作,可使用 cache_control 視圖修飾器: 例如:

from django.views.decorators.cache import cache_control

@cache_control(private=True)
def my_view(request):
    # ...

該修飾器負(fù)責(zé)在后臺發(fā)送相應(yīng)的 HTTP 頭部。

還有一些其他方法可以控制緩存參數(shù)。 例如, HTTP 允許應(yīng)用程序執(zhí)行如下操作:

  • 定義頁面可以被緩存的最大時間。

  • 指定某個緩存是否總是檢查較新版本,僅當(dāng)無更新時才傳遞所緩存內(nèi)容。 (一些緩存即便在服務(wù)器頁面發(fā)生變化的情況下仍然會傳送所緩存的內(nèi)容,只因?yàn)榫彺婵截悰]有過期。)

在 Django 中,可使用 cache_control 視圖修飾器指定這些緩存參數(shù)。 在本例中, cache_control 告訴緩存對每次訪問都重新驗(yàn)證緩存并在最長 3600 秒內(nèi)保存所緩存版本:

from django.views.decorators.cache import cache_control

@cache_control(must_revalidate=True, max_age=3600)
def my_view(request):
    # ...

在 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

緩存中間件已經(jīng)使用 CACHE_MIDDLEWARE_SETTINGS 設(shè)置設(shè)定了緩存頭部 max-age 。 如果你在cache_control修飾器中使用了自定義的max_age,該修飾器將會取得優(yōu)先權(quán),該頭部的值將被正確地被合并。

如果你想用頭部完全禁掉緩存,django.views.decorators.cache.never_cache裝飾器可以添加確保響應(yīng)不被緩存的頭部信息。 例如:

from django.views.decorators.cache import never_cache

@never_cache
def myview(request):
    # ...

其他優(yōu)化

Django 帶有一些其它中間件可幫助您優(yōu)化應(yīng)用程序的性能:

  • django.middleware.http.ConditionalGetMiddleware 為現(xiàn)代瀏覽器增加了有條件的,基于 ETag 和Last-Modified 頭標(biāo)的GET響應(yīng)的相關(guān)支持。

  • django.middleware.gzip.GZipMiddleware 為所有現(xiàn)代瀏覽器壓縮響應(yīng)內(nèi)容,以節(jié)省帶寬和傳送時間。

MIDDLEWARE_CLASSES 的順序

如果使用緩存中間件,注意在MIDDLEWARE_CLASSES設(shè)置中正確配置。 因?yàn)榫彺嬷虚g件需要知道哪些頭部信息由哪些緩存區(qū)來區(qū)分。 中間件總是盡可能得想Vary響應(yīng)頭中添加信息。

UpdateCacheMiddleware在相應(yīng)階段運(yùn)行。因?yàn)橹虚g件是以相反順序運(yùn)行的,所有列表頂部的中間件反而_last_在相應(yīng)階段的最后運(yùn)行。 所有,你需要確保UpdateCacheMiddleware排在任何可能往_Vary_頭部添加信息的中間件之前。 下面的中間件模塊就是這樣的:

  • 添加 Cookie 的 SessionMiddleware

  • 添加 Accept-Encoding 的 GZipMiddleware

  • 添加Accept-Language的LocaleMiddleware

另一方面,F(xiàn)etchFromCacheMiddleware在請求階段運(yùn)行,這時中間件循序執(zhí)行,所以列表頂端的項(xiàng)目會_首先_執(zhí)行。 FetchFromCacheMiddleware也需要在會修改Vary頭部的中間件之后運(yùn)行,所以FetchFromCacheMiddleware必須放在它們后面。

下一章

Django捆綁了一系列可選的方便特性。 我們已經(jīng)介紹了一些: admin站點(diǎn)(第六章)和session/user框架(第十四章)。 下一章中,我們將講述Django中其他的子框架。

關(guān)閉
程序員人生
主站蜘蛛池模板: www视频在线观看 | 久久久福利 | 国产视频一区二区三区四区 | 91你懂的 | 91社影院在线观看 | 91视频一区二区 | 日韩欧美亚洲国产精品字幕久久久 | 丁香久久五月 | 国产精品毛片va一区二区三区 | 自拍第一页 | 久久久久国产精品免费免费搜索 | 国产久| 99久久久久久 | 亚洲欧美在线播放 | 精品视频在线观看 | 国产a区 | 99精品在线| 午夜久久久久 | 中文字幕日韩av | 精品成人一区二区 | 日韩在线精品强乱中文字幕 | 91精品国产99久久久久久红楼 | 国产精品久久久久毛片软件 | 亚洲成人高清在线观看 | 国产一卡二卡在线 | 国产精品第8页 | 国产精品久久久久一区二区三区 | 国产精品一区三区 | 91久久精品一区二区 | 久久大陆 | 亚洲乱码一区二区三区在线观看 | 日韩欧美精品在线观看 | 久久亚洲精品国产日韩潮高 | 国产精品免费一区二区三区都可以 | 在线免费黄色小视频 | 日本午夜网| 国产精品久久久久久久久久嫩草 | 日韩精品视频一区二区三区 | 亚洲一区二区三区四区不卡 | 人成在线 | 污污视频免费观看 |