Amazon CloudFront 未針對未更改的靜態內容始終返回 304(未修改)?
EC2 Web 伺服器網格在 ELB 負載均衡器後面執行。ELB 位於 Amazon 的 CloudFront 內容傳遞網路的背後。內容傳遞網路對我來說非常陌生。我的理解是 CloudFront 應該通過在其“邊緣”記憶體靜態內容來提高性能。但這不是正在發生的事情。
考慮我的 EC2 實例,其內容的生命週期應始終為五分鐘。對於靜態內容,這通常意味著在我的 web.config 文件中聲明以下內容:
<staticContent> <clientCache cacheControlCustom="public" cacheControlMode="UseMaxAge" cacheControlMaxAge="00.00:05:00"/> </staticContent>…對於動態的東西,它通常意味著對 HttpResponse 對象執行以下命令:
resp.Cache.SetCacheability(HttpCacheability.Public); resp.Cache.SetMaxAge(TimeSpan.FromMinutes(5));以此為背景…
當我的瀏覽器直接點擊 ELB時,一切都按預期工作。Firebug 始終顯示對於存在於瀏覽器記憶體中的內容返回 304(未修改),已超過 5 分鐘過期時間,但在伺服器上尚未更改。以下是下載 defs.js 的響應標頭,例如:
HTTP/1.1 304 Not Modified Accept-Ranges: bytes Cache-Control: public,max-age=300 Date: Tue, 22 Apr 2014 13:54:16 GMT Etag: "0152435d158cf1:0" Last-Modified: Tue, 15 Apr 2014 17:36:18 GMT Server: Microsoft-IIS/7.5 X-Powered-By: ASP.NET Connection: keep-aliveIIS 正確地看到該文件自 4 月 15 日以來未更改並返回 304。
但是看看通過 CloudFront 抓取文件時會發生什麼。
HTTP/1.1 200 OK Content-Type: application/x-javascript Content-Length: 205 Connection: keep-alive Accept-Ranges: bytes Cache-Control: public,max-age=300 Date: Tue, 22 Apr 2014 14:07:33 GMT Etag: "0152435d158cf1:0" Last-Modified: Tue, 15 Apr 2014 17:36:18 GMT Server: Microsoft-IIS/7.5 X-Powered-By: ASP.NET Age: 16 X-Cache: Hit from cloudfront Via: 1.1 0f140ef1be762325ad24a7167aa57e65.cloudfront.net (CloudFront) X-Amz-Cf-Id: Evfdhs-pxFojnzkQWuG-Ubp6B2TC5xbunhavG8ivXURdp2fw_noXjw==在這種情況下,CloudFront 會強制瀏覽器再次下載整個文件,儘管您可以看到:
(a) 它知道該文件自 4 月 15 日以來沒有被修改過(請參閱 Last-Modified 標頭),並且 (b) CloudFront 確實有該文件的記憶體副本(請參閱 X-Cache 標頭)
也許您想知道我的瀏覽器是否正在發送有效的 If-Modified-Since 標頭。它的確是。以下是請求標頭:
GET /code/shared/defs.js HTTP/1.1 Host: d2fn6fv5a0cu3b.cloudfront.net User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:28.0) Gecko/20100101 Firefox/28.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate DNT: 1 Referer: http://d2fn6fv5a0cu3b.cloudfront.net/ Connection: keep-alive If-Modified-Since: Tue, 15 Apr 2014 17:36:18 GMT If-None-Match: "0152435d158cf1:0" Cache-Control: max-age=0這是一個奇怪的情況。如果我只是坐在瀏覽器前並繼續執行頁面重新載入 (Cmd-R),可能大約一半的時間 CloudFront 會正確返回 304,而另一半時間它會錯誤地返回 200 以及所有內容. 在與頁面互動之前等待 5 分鐘到期,主要是 200 和只有少數 304。這種奇怪的行為適用於 HTML 頁面上引用的所有文件(.css、.js、.png 等)以及包含的 HTML 頁面本身。我知道我的應用程序編碼正確,因為如上所述,直接訪問 ELB 而不通過 CloudFront 會導致預期的 304 結果。有任何想法嗎?
答案是在一段看似無關的亞馬遜文件中寫的一個晦澀的句子中找到的:
When you configure CloudFront to forward cookies to your origin [...] If-Modified-Since and If-None-Match conditional requests are not supported.奇怪,但實際情況確實要糟糕得多;並不是將 cookie 轉發到您的源伺服器會禁用條件請求,而是有時會禁用它們——以至於 HTTP 結果程式碼(304 與 200)實際上是隨機的。
請務必注意,即使您根本不使用 cookie,您也會被這種奇怪的行為所困擾。將 Forward Cookies 下拉菜單設置為“None”仍然是絕對必要的,如下圖所示:
將設置切換為“無”修復了我原始文章中描述的錯誤行為。
但是,此解決方案給您帶來了另一個問題。您告訴 CloudFront 在將請求轉發到您的源之前完全刪除所有 cookie。但是您的原始伺服器可能需要這些 cookie。此外,如果您使用 ELB(負載均衡器)作為源,ELB 用來維持粘性會話的關鍵 cookie 將被完全刪除。不好。
cookie 剝離問題的解決方案將取決於您的網站的組織方式。就我而言,只有在將 AJAX 數據發佈到
myDomain.com/ajax/. 由於所有依賴於 cookie 的 URL 都屬於 類別ajax/*,因此必須為該路徑創建一個新的行為規則,並且在該規則中,並且僅在該規則中,轉發 Cookie 下拉菜單設置為“全部”而不是“無”。 "就這樣。希望這可以幫助某人。
