成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

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

番茄西紅柿 / 2905人閱讀

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

作者: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 或者根本負擔不起其價格,不過這一現(xiàn)象近幾年發(fā)生了很大的變化,CDN 市場上出現(xiàn)了很多按次付費,非公司性的提供商,這使得 CDN 變成人人都能負擔的起的一種服務了。本文講述的就是如何使用這種簡單易用的緩存服務。

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

Cookies

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

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

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

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

正確處理 cookie 和緩存

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

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

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

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

其實,如果從應用層面來講,你盡管可以去實現(xiàn)你所喜歡的 web 應用就可以了,至于 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è)置一個默認值;

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

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

無 cookie 的訪問路徑

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

所以下面這個例子是否適合你自己,很大程度上依賴于你的應用到底是什么類型的。我們來一起看一下,我先給一下這個例子的上下文關(guān)系:假設(shè)你有個新網(wǎng)站,你的所有文章都在 http://www.foobar.tld/news/it... 這個路徑下面?,F(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。而到底是否應該設(shè)置 cookie,需要你根據(jù)你自己的應用特點來判斷。

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

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

我還用電商作為例子。假設(shè)電商網(wǎng)站首頁的 top 位置上展示了正在出售的物品,生成這些物品需要進行若干次的數(shù)據(jù)庫操作,代價比較大,因此希望把它們緩存起來。但是,問題在于購物車,它是為那些登陸用戶準備的,所以希望得到的結(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)可以很好地控制一個指定的響應被緩存多長時間。但是這不足以適用于所有的情況。這些設(shè)置都是在返回響應時預設(shè)的,而現(xiàn)實情況往往是并不知道一個響應應該設(shè)置多久期滿。回想一下剛才電商首頁的例子:假設(shè)它包含了展示在 top 位置的 10 個實體。你設(shè)置了 max-age=900給這個首頁以保證每15分鐘刷新一次?,F(xiàn)在,其中 1 個實體由于發(fā)布了太久了要被撤銷,那么你就需要把之前的緩存響應刪掉,這時候其實還沒到 15 分鐘,那么該怎么辦?

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

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

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

用于版本管理的緩存 busting

這種方法經(jīng)常使用在 CSS 文件、JS 文件上。通常一個確切的版本號、一串哈?;蛘邥r間戳都可以用作標識,如下面的例子:

數(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 供應商清除緩存的方式不一樣。很多供應商都是基于開源軟件 Varnish 來構(gòu)建自己的 CDN 服務,所以一個通用的做法是在 HTPP 請求中使用 PURGE 結(jié)構(gòu),如:

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

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

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

下面介紹一個解決方案。

代理標簽

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

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

還是拿<客戶端-代理-源端>來舉例子,源端返回一個含有代理標簽的響應:

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

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

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

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

寫在最后

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

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

Push CDN 和 Pull CDN

CDN 類型(管理員視角)

緩存頭概覽

緩存詳解(Mozilla)

ETag頭詳解(Mozilla)

Cace-Control 頭詳解(Mozilla)

If-None-Match 頭詳解(Mozilla)

Fastly:代理標簽

KeyCDN:緩存標簽

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


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

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/33789.html

相關(guān)文章

  • 掌握 HTTP 緩存——請求響應過程一切

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

    Gilbertat 評論0 收藏0
  • 掌握 HTTP 緩存——請求響應過程一切

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

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

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

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

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

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

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

    whlong 評論0 收藏0

發(fā)表評論

0條評論

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