HTTP 緩存(HTTP Caching)

2018-02-24 15:40 更新

HTTP 緩存

除了前面章節(jié)講到的服務(wù)器端緩存外, Web 應(yīng)用還可以利用客戶端緩存去節(jié)省相同頁面內(nèi)容的生成和傳輸時間。

通過配置 yii\filters\HttpCache 過濾器,控制器操作渲染的內(nèi)容就能緩存在客戶端。yii\filters\HttpCache 過濾器僅對?GET?和?HEAD?請求生效,它能為這些請求設(shè)置三種與緩存有關(guān)的 HTTP 頭。

  • yii\filters\HttpCache::lastModified
  • yii\filters\HttpCache::etagSeed
  • yii\filters\HttpCache::cacheControlHeader

Last-Modified?頭

Last-Modified?頭使用時間戳標(biāo)明頁面自上次客戶端緩存后是否被修改過。

通過配置 yii\filters\HttpCache::lastModified 屬性向客戶端發(fā)送?Last-Modified?頭。該屬性的值應(yīng)該為 PHP callable 類型,返回的是頁面修改時的 Unix 時間戳。該 callable 的參數(shù)和返回值應(yīng)該如下:

/**
 * @param Action $action 當(dāng)前處理的操作對象
 * @param array $params “params” 屬性的值
 * @return integer 頁面修改時的 Unix 時間戳
 */
function ($action, $params)

以下是使用?Last-Modified?頭的示例:

public function behaviors()
{
    return [
        [
            'class' => 'yii\filters\HttpCache',
            'only' => ['index'],
            'lastModified' => function ($action, $params) {
                $q = new \yii\db\Query();
                return $q->from('post')->max('updated_at');
            },
        ],
    ];
}

上述代碼表明 HTTP 緩存只在?index?操作時啟用。它會基于頁面最后修改時間生成一個?Last-Modified?HTTP 頭。當(dāng)瀏覽器第一次訪問?index?頁時,服務(wù)器將會生成頁面并發(fā)送至客戶端瀏覽器。之后客戶端瀏覽器在頁面沒被修改期間訪問該頁,服務(wù)器將不會重新生成頁面,瀏覽器會使用之前客戶端緩存下來的內(nèi)容。因此服務(wù)端渲染和內(nèi)容傳輸都將省去。

ETag?頭

“Entity Tag”(實體標(biāo)簽,簡稱 ETag)使用一個哈希值表示頁面內(nèi)容。如果頁面被修改過,哈希值也會隨之改變。通過對比客戶端的哈希值和服務(wù)器端生成的哈希值,瀏覽器就能判斷頁面是否被修改過,進(jìn)而決定是否應(yīng)該重新傳輸內(nèi)容。

通過配置 yii\filters\HttpCache::etagSeed 屬性向客戶端發(fā)送?ETag?頭。該屬性的值應(yīng)該為 PHP callable 類型,返回的是一段種子字符用來生成 ETag 哈希值。該 callable 的參數(shù)和返回值應(yīng)該如下:

/**
 * @param Action $action 當(dāng)前處理的操作對象
 * @param array $params “params” 屬性的值
 * @return string 一段種子字符用來生成 ETag 哈希值
 */
function ($action, $params)

以下是使用?ETag?頭的示例:

public function behaviors()
{
    return [
        [
            'class' => 'yii\filters\HttpCache',
            'only' => ['view'],
            'etagSeed' => function ($action, $params) {
                $post = $this->findModel(\Yii::$app->request->get('id'));
                return serialize([$post->title, $post->content]);
            },
        ],
    ];
}

上述代碼表明 HTTP 緩存只在?view?操作時啟用。它會基于用戶請求的標(biāo)題和內(nèi)容生成一個?ETag?HTTP 頭。當(dāng)瀏覽器第一次訪問view?頁時,服務(wù)器將會生成頁面并發(fā)送至客戶端瀏覽器。之后客戶端瀏覽器標(biāo)題和內(nèi)容沒被修改在期間訪問該頁,服務(wù)器將不會重新生成頁面,瀏覽器會使用之前客戶端緩存下來的內(nèi)容。因此服務(wù)端渲染和內(nèi)容傳輸都將省去。

ETag 相比?Last-Modified?能實現(xiàn)更復(fù)雜和更精確的緩存策略。例如,當(dāng)站點切換到另一個主題時可以使 ETag 失效。

復(fù)雜的 Etag 生成種子可能會違背使用?HttpCache?的初衷而引起不必要的性能開銷,因為響應(yīng)每一次請求都需要重新計算 Etag。請試著找出一個最簡單的表達(dá)式去觸發(fā) Etag 失效。

注意:為了遵循?RFC 7232(HTTP 1.1 協(xié)議),如果同時配置了?ETag?和?Last-Modified?頭,HttpCache?將會同時發(fā)送它們。并且如果客戶端同時發(fā)送?If-None-Match?頭和?If-Modified-Since?頭,則只有前者會被接受。

Cache-Control?頭

Cache-Control?頭指定了頁面的常規(guī)緩存策略??梢酝ㄟ^配置 yii\filters\HttpCache::cacheControlHeader 屬性發(fā)送相應(yīng)的頭信息。默認(rèn)發(fā)送以下頭:

Cache-Control: public, max-age=3600

會話緩存限制器

當(dāng)頁面使 session 時,PHP 將會按照 PHP.INI 中所設(shè)置的?session.cache_limiter?值自動發(fā)送一些緩存相關(guān)的 HTTP 頭。這些 HTTP 頭有可能會干擾你原本設(shè)置的?HttpCache?或讓其失效。為了避免此問題,默認(rèn)情況下?HttpCache?禁止自動發(fā)送這些頭。想改變這一行為,可以配置 yii\filters\HttpCache::sessionCacheLimiter 屬性。該屬性接受一個字符串值,包括public,private,private_no_expire,和?nocache。請參考 PHP 手冊中的緩存限制器了解這些值的含義。

SEO 影響

搜索引擎趨向于遵循站點的緩存頭。因為一些爬蟲的抓取頻率有限制,啟用緩存頭可以可以減少重復(fù)請求數(shù)量,增加爬蟲抓取效率(譯者:大意如此,但搜索引擎的排名規(guī)則不了解,好的緩存策略應(yīng)該是可以為用戶體驗加分的)。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號