国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

掌握 HTTP 緩存——從請求到響應(yīng)過程的一切(下)

Gilbertat / 1190人閱讀

摘要:上篇文章掌握緩存從請求到響應(yīng)過程的一切上我們討論了關(guān)于利用頭來解決緩存問題,這篇文章我們將介紹緩存和之間的關(guān)系。文件將會被緩存起來,這時如果你想讓你的新文件起作用,那么用最新的版本號命名它就可以。緩存不同供應(yīng)商清除緩存的方式不一樣。

作者:Ulrich Kautz

編譯:胡子大哈

翻譯原文:http://huziketang.com/blog/posts/detail?postId=58bd4dd1204d50674934c3b0

英文原文:Mastering HTTP Caching - from request to response and everything

轉(zhuǎn)載請注明出處,保留原文鏈接以及作者信息


CDN類的網(wǎng)站曾經(jīng)一度雄踞 Alexa 域名排行的前 100。以前一些小網(wǎng)站不需要使用 CDN 或者根本負(fù)擔(dān)不起其價格,不過這一現(xiàn)象近幾年發(fā)生了很大的變化,CDN 市場上出現(xiàn)了很多按次付費,非公司性的提供商,這使得 CDN 變成人人都能負(fù)擔(dān)的起的一種服務(wù)了。本文講述的就是如何使用這種簡單易用的緩存服務(wù)。

上篇文章《掌握 HTTP 緩存——從請求到響應(yīng)過程的一切(上)》我們討論了關(guān)于利用 HTTP 頭來解決緩存問題,這篇文章我們將介紹緩存和 Cookie之間的關(guān)系。

Cookies

你已經(jīng)知道了緩存頭是如何起作用的,現(xiàn)在我們來看下在緩存里面 cookie 起了什么作用。首先, Cookie 的設(shè)定也在 HTTP 響應(yīng)頭中,名字是 Set-Cookie。設(shè)置一個 cookie 的目的是標(biāo)識這個用戶,就是說你需要為每個用戶設(shè)置一個 cookie。

想象一下緩存的場景,你是否會緩存一個包含了 Set-Cookie的 HTTP 響應(yīng),在緩存時間內(nèi),每個人都會得到相同的 cookie 和同樣的用戶 session?你肯定不想這樣。

另外,用戶 session 狀態(tài)的改變可能會影響到響應(yīng)內(nèi)容的變化。一個簡單的場景:電商購物車。你給用戶要么提供一個空購物車,要么是用戶自己選了很多物品的購物車。同樣的道理,你不希望這個也被緩存,畢竟每個用戶都應(yīng)該有自己的購物車。

一個解決方法是在運行時通過 JavaScript 設(shè)置 Cookie,比如 Google Analytics。GA 通過 JS 設(shè)置 cookie,但這個 cookie 既不影響渲染,也不設(shè)置 Set-Cookie 頭。GA 會在目標(biāo)網(wǎng)站上添加類似于 "you are tracked via Google Analytics" 的圖標(biāo),但是只要這些改變都是在運行時添加進(jìn)去的,就都沒有問題

正確處理 cookie 和緩存

首先你需要知道你網(wǎng)站的 cookie 的工作原理。cookie 是不是只在特定時間使用(如在用戶登錄過程中使用)?原則上,cookie 是不是會被注入到所有響應(yīng)?

正如上一節(jié)所說的,不論何時服務(wù)器返回了一個帶有 Set-Cookie 的響應(yīng),你都希望能夠保證它不會被緩存。那么問題就轉(zhuǎn)化成為,當(dāng)你返回一個帶有“用戶特性”內(nèi)容的響應(yīng)時(如購物車),CDN /代理服務(wù)器,會作何操作?

如果沒設(shè)置 Set-Cookie,是不是允許緩存呢?

如果設(shè)置了 Set-Cookie,是不是自動丟棄所有 Cache-Control 頭呢?

其實,如果從應(yīng)用層面來講,你盡管可以去實現(xiàn)你所喜歡的 web 應(yīng)用就可以了,至于 cookie 和 CDN 都是自動設(shè)置的。還是用 Apache 的 .htaccess 來作為例子來解釋:

# 1) 如果 cookie 沒設(shè)置,允許緩存
Header set Cache-Control "public max-age=3600" "expr=-z resp("Set-Cookie")

# 2) 如果 cookie 被設(shè)置,不允許緩存
Header always remove Cache-Control "expr=-n resp("Set-Cookie")

# 2a) 第二條的另一種形式,如果設(shè)置了 cookie,緩存時間設(shè)置成0
Header set Cache-Control "no-cache max-age=0 must-revalidate" "expr=-n resp("Set-Cookie")

規(guī)則1:如果沒設(shè)置 Set-Cookie,則給 Cache-Control 設(shè)置一個默認(rèn)值;

規(guī)則2:如果設(shè)置了 Set-Cookie,則忽略 Cache-Control

規(guī)則2a:是規(guī)則2的另一種表示形式,設(shè)置最大緩存時間是 0。

無 cookie 的訪問路徑

一些 CMS /框架還在使用一種暴力的方式種 cookie。而實際上,決定是否種 cookie 取決于不同的因素,比如會話時間因素。如果你有一個很高安全性的 web 應(yīng)用,設(shè)置會話時間是 5 分鐘,那么為每個響應(yīng)設(shè)置一個新 cookie 都不過分。而假設(shè)你的應(yīng)用連“用戶特性”都沒有,也就是說所有的東西對所有用戶都是公用的,那么設(shè)置任何形式的 cookie 都是沒有道理的。

所以下面這個例子是否適合你自己,很大程度上依賴于你的應(yīng)用到底是什么類型的。我們來一起看一下,我先給一下這個例子的上下文關(guān)系:假設(shè)你有個新網(wǎng)站,你的所有文章都在 http://www.foobar.tld/news/it... 這個路徑下面。現(xiàn)在你希望能夠保證,所有訪問 /news/item/ 的路徑都不包含 Set-Cookie,因為你確定不需要 cookie。

# 通用 PHP 重定向做法,將"?path=$1"寫到重定向規(guī)則里
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?path=$1 [NC,L,QSA]
RewriteRule ^$ index.php [NC,L,QSA]

# 利用 query 中的 path= 來判斷

    Header always unset Set-Cookie

通過這樣的設(shè)置,你就可以保證所有訪問 /news/item/ 的路徑都不包含 Set-Cookie。而到底是否應(yīng)該設(shè)置 cookie,需要你根據(jù)你自己的應(yīng)用特點來判斷。

設(shè)計出來的緩存能力

有很多設(shè)計方案可以使你的 web 應(yīng)用具有高緩存性。鑒于本文僅僅是一篇文章而不是一本書,我不可能每個點都深入的來講,但是我可以著重提一下通用的方法。

我還用電商作為例子。假設(shè)電商網(wǎng)站首頁的 top 位置上展示了正在出售的物品,生成這些物品需要進(jìn)行若干次的數(shù)據(jù)庫操作,代價比較大,因此希望把它們緩存起來。但是,問題在于購物車,它是為那些登陸用戶準(zhǔn)備的,所以希望得到的結(jié)果是: top 物品是一樣的,而針對登陸用戶展示購物車。

那么優(yōu)化策略首先要為每個用戶提供一個和登陸狀態(tài)無關(guān)的“通用”頁。然后通過 JavaScript 為已經(jīng)生成的網(wǎng)頁提供購物車。站在用戶的視角,最終展示形式是一樣的。那么現(xiàn)在你有了兩個請求(整個網(wǎng)頁請求 + 購物車請求),而不是一個請求(整個網(wǎng)頁請求,包含購物車)。ok,現(xiàn)在你可以把代價很大的部分,即 top 物品分離出來,把它們緩存起來了。

這種方法或者其延伸方法,不適合已經(jīng)開發(fā)好的項目。因為它可能會改變很多接口和視圖層(MVC 架構(gòu))的內(nèi)容。最好你在一開始就設(shè)計好。

緩存失效:busting 和 purging

使用 max-ages-maxage 你已經(jīng)可以很好地控制一個指定的響應(yīng)被緩存多長時間。但是這不足以適用于所有的情況。這些設(shè)置都是在返回響應(yīng)時預(yù)設(shè)的,而現(xiàn)實情況往往是并不知道一個響應(yīng)應(yīng)該設(shè)置多久期滿。回想一下剛才電商首頁的例子:假設(shè)它包含了展示在 top 位置的 10 個實體。你設(shè)置了 max-age=900給這個首頁以保證每15分鐘刷新一次。現(xiàn)在,其中 1 個實體由于發(fā)布了太久了要被撤銷,那么你就需要把之前的緩存響應(yīng)刪掉,這時候其實還沒到 15 分鐘,那么該怎么辦?

不要擔(dān)心,這是一個常見的問題,有很多方法解決。首先我們先來解釋一下術(shù)語:

緩存 busting,是用來解決瀏覽器長期緩存問題,它通過版本標(biāo)識來告訴瀏覽器該文件有一個新的版本。這時瀏覽器將不會從本地緩存取內(nèi)容,而從源服務(wù)器請求新版本的文件。關(guān)于緩存 busting的詳細(xì)介紹在這里:What is Cache Busting?。

緩存 purging,表示直接從緩存中刪除內(nèi)容(即響應(yīng)),以使得緩存可以立馬得到更新。

用于版本管理的緩存 busting

這種方法經(jīng)常使用在 CSS 文件、JS 文件上。通常一個確切的版本號、一串哈希或者時間戳都可以用作標(biāo)識,如下面的例子:

數(shù)字版本號:style-v1.cssstyle.css?v=1

哈希串版本:style.css?d3b07384d113edec49eaa6238ad5ff00

時間戳版本:styles.css?t=1486398121

這時候在發(fā)布程序的時候,你只要注意文件的版本就可以了。舉個例子,一個 HTML 網(wǎng)頁通過 這種形式包含了一個 CSS 文件。CSS 文件將會被緩存起來,這時如果你想讓你的新 CSS 文件起作用,那么用最新的版本號命名它就可以。如果不做任何變化的話,即便你更新了文件,這個 HTML 還會使用緩存中的舊 CSS 文件。

緩存 purging

不同 CDN 供應(yīng)商清除緩存的方式不一樣。很多供應(yīng)商都是基于開源軟件 Varnish 來構(gòu)建自己的 CDN 服務(wù),所以一個通用的做法是在 HTPP 請求中使用 PURGE 結(jié)構(gòu),如:

PURGE /news/item/i-am-obsolete HTTP/1.1
Host: www.foobar.tld

使用這個請求通常需要權(quán)限認(rèn)證,或者是源確認(rèn)(即 IP 白名單),不過不同供應(yīng)商的要求也不一樣。

清除一個或幾個緩存項比較容易,但是在某些場景下,卻不是這么簡單。舉個例子,一個博客的場景,博客里面都有關(guān)于作者的部分,現(xiàn)在你要改變關(guān)于作者的一些內(nèi)容,那么你需要手動清理所有包含了作者信息的頁面。你確實可以一個一個手動清理,但是假設(shè)你有成千上萬個網(wǎng)頁被影響了,那問題就變得麻煩了。

下面介紹一個解決方案。

代理標(biāo)簽

“代理標(biāo)簽” 這個名字來源于 CDN 供應(yīng)商 Fastly,不同供應(yīng)商給它起的名字不一樣,比如還有叫它“緩存標(biāo)簽”的,Varnish 叫它 Hashtwo/Xkey,這里我就不詳細(xì)介紹其他供應(yīng)商的情況了。

不論它叫什么,它們的目的都是一樣的:給響應(yīng)打標(biāo)簽。這樣你就可以輕松地從緩存中刪除相關(guān)的標(biāo)簽就可以,甚至都不用知道緩存的到底是什么東西。

還是拿<客戶端-代理-源端>來舉例子,源端返回一個含有代理標(biāo)簽的響應(yīng):

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 123
Surrogate-Key: top-10 company-acme category-foodstuff

這個例子中的標(biāo)簽為:top-10company-acme,和 category-foodstuff。這里給一個電商的實際場景來理解其含義:這個響應(yīng)包含了電商首頁的前 10 個物品,這些物品由 ACME 公司提供,并且其目錄類別都設(shè)定為食品類。

設(shè)置了標(biāo)簽以后,當(dāng)物品發(fā)生了變化以后,你只需要刪除包含有 company-acmetop-10 的標(biāo)簽就可以了。是不是很簡單?

同樣,具體如何清除緩存的操作方法,不同 CDN 供應(yīng)商是不一樣的。

寫在最后

上面討論的更多的是理論上的做法,還有很多文章專門介紹不同的 CDN 的使用。如果你想深入了解的話,下面的資料每篇可能都是你需要的。

谷歌開發(fā)者:HTTP 緩存

Push CDN 和 Pull CDN

CDN 類型(管理員視角)

緩存頭概覽

緩存詳解(Mozilla)

ETag頭詳解(Mozilla)

Cace-Control 頭詳解(Mozilla)

If-None-Match 頭詳解(Mozilla)

Fastly:代理標(biāo)簽

KeyCDN:緩存標(biāo)簽

歡迎大家關(guān)注我的前端大哈 - 知乎專欄,定期發(fā)布高質(zhì)量前端文章。


我最近正在寫一本《React.js 小書》,對 React.js 感興趣的童鞋,歡迎指點。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/61839.html

相關(guān)文章

  • 掌握 HTTP 緩存——請求響應(yīng)過程一切

    摘要:上篇文章掌握緩存從請求到響應(yīng)過程的一切上我們討論了關(guān)于利用頭來解決緩存問題,這篇文章我們將介紹緩存和之間的關(guān)系。文件將會被緩存起來,這時如果你想讓你的新文件起作用,那么用最新的版本號命名它就可以。緩存不同供應(yīng)商清除緩存的方式不一樣。 作者:Ulrich Kautz 編譯:胡子大哈 翻譯原文:http://huziketang.com/blog/posts/detail?postId=...

    番茄西紅柿 評論0 收藏0
  • 掌握 HTTP 緩存——請求響應(yīng)過程一切

    摘要:上篇文章掌握緩存從請求到響應(yīng)過程的一切上我們討論了關(guān)于利用頭來解決緩存問題,這篇文章我們將介紹緩存和之間的關(guān)系。文件將會被緩存起來,這時如果你想讓你的新文件起作用,那么用最新的版本號命名它就可以。緩存不同供應(yīng)商清除緩存的方式不一樣。 作者:Ulrich Kautz 編譯:胡子大哈 翻譯原文:http://huziketang.com/blog/posts/detail?postId=...

    ninefive 評論0 收藏0
  • 前端小白中高級前端需要掌握技能總結(jié)(2)

    摘要:這個系列的文章的第二篇,繼續(xù)總結(jié)這是從一個問題上衍生出的知識體系,這個問題是從輸入到頁面加載的過程。先梳理下這個流程第一步從瀏覽器接收到開啟網(wǎng)絡(luò)請求線程瀏覽器的進(jìn)程線程模型,的運行機(jī)制瀏覽器的進(jìn)程瀏覽器是多進(jìn)程的。 這個系列的文章的第二篇,繼續(xù)總結(jié)~~ 這是從一個問題上衍生出的知識體系,這個問題是從輸入URL到頁面加載的過程。先梳理下這個流程 第一步 從瀏覽器接收url到開啟網(wǎng)絡(luò)請求線...

    xiaoxiaozi 評論0 收藏0
  • 前端小白中高級前端需要掌握技能總結(jié)(2)

    摘要:這個系列的文章的第二篇,繼續(xù)總結(jié)這是從一個問題上衍生出的知識體系,這個問題是從輸入到頁面加載的過程。先梳理下這個流程第一步從瀏覽器接收到開啟網(wǎng)絡(luò)請求線程瀏覽器的進(jìn)程線程模型,的運行機(jī)制瀏覽器的進(jìn)程瀏覽器是多進(jìn)程的。 這個系列的文章的第二篇,繼續(xù)總結(jié)~~ 這是從一個問題上衍生出的知識體系,這個問題是從輸入URL到頁面加載的過程。先梳理下這個流程 第一步 從瀏覽器接收url到開啟網(wǎng)絡(luò)請求線...

    cartoon 評論0 收藏0
  • 前端小白中高級前端需要掌握技能總結(jié)(2)

    摘要:這個系列的文章的第二篇,繼續(xù)總結(jié)這是從一個問題上衍生出的知識體系,這個問題是從輸入到頁面加載的過程。先梳理下這個流程第一步從瀏覽器接收到開啟網(wǎng)絡(luò)請求線程瀏覽器的進(jìn)程線程模型,的運行機(jī)制瀏覽器的進(jìn)程瀏覽器是多進(jìn)程的。 這個系列的文章的第二篇,繼續(xù)總結(jié)~~ 這是從一個問題上衍生出的知識體系,這個問題是從輸入URL到頁面加載的過程。先梳理下這個流程 第一步 從瀏覽器接收url到開啟網(wǎng)絡(luò)請求線...

    whlong 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<