先說背景。網站是用PHP開發的,未用任何框架,代碼結構也很是簡單。運行於阿里雲服務器,並採用其CDN來作分發。根據業務需求,有的頁面會判斷用戶瀏覽器類型,依此來選擇PC或者手機端內容。php
在一次上線過程當中,遇到比較詭異的問題:用PC和手機分別訪問頁面時,網頁內容未根據瀏覽器類型來區分。而在開發環境,頁面卻能正常顯示。仔細排查了代碼,沒有發現問題出在什麼地方。而線上環境也很差調試,只能靠猜了。
css
開發環境一切正常,說明代碼出問題的可能性不大(固然後面發現仍是代碼的問題~)。而線上與開發環境的差異就在於多了一層CDN。會不會是CDN的問題?然而本人對CDN也是隻知其一;不知其二的,只知道是它會緩存源網站內容,並就近對用戶進行內容分發,來加速訪問。若是用戶請求的內容CDN並未緩存,就會發生回源。對圖片、css、js等靜態資源,CDN緩存是理所應當的。可是對html內容,由於通常都是PHP動態生成的,會有一些業務邏輯,緩存這些內容就不太合適了。因爲相關判斷瀏覽器類型的代碼是通過驗證的,因此問題應該不在網站自己。考慮到上面CDN相關內容,我就在懷疑是否是CDN把html都緩存下來了,致使用戶請求壓根沒到網站服務器。因而打開瀏覽器console,查看請求響應頭,並把問題頁的響應頭和正常頁面進行對比,果真發現了問題。正常頁面每次刷新後,響應頭裏的Date字段都會改變;而問題頁的Date字段一直沒變化!也就是說問題頁取到的內容一直都是CDN緩存。再次對比發現,正常頁面還有Cache-Control相關內容,而問題頁沒有。因而推測CDN會根據響應頭來決定是否會緩存內容。在問題頁代碼中增長緩存控制相關header後,果真正常了。然而問題又來了,正常頁面的Cache-Control是哪裏輸出的呢?代碼中並無看到對應內容,估計是線上人爲加了相關header,與開發環境代碼不一致。html
一直以來對http響應頭中的緩存控制相關內容都沒有注意,遇到問題才發現它們的重要性。本次解決這個問題,主要是增長了如下header:瀏覽器
header('Pragma: no-cache');//兼容老版本協議 http1.0可能不識別Cache-Control header('Cache-Control: no-store, no-cache, must-revalidate');//告訴瀏覽器/代理 不緩存內容 header("Expires: Mon, 26 Jul 1970 05:00:00 GMT"); //把過時時間設置爲以往的時間,基本等同於Cache-Control:no-cache
頁面加上三行代碼後基本可保證其內容不被緩存。緩存
阿里雲CDN響應頭中有幾個關於緩存的字段須要注意:服務器
X-Cache,值包含HIT時,表示命中緩存;MISS則表示未命中,須要回源 X-Swift-SaveTime 緩存保存時間 X-Swift-CacheTime 緩存時長 Age 當前資源已緩存的時間,達到X-Swift-CacheTime時緩存過時,會回源
想了解更多HTTP協議相關內容,請查看HTTP協議簡介框架