《PHP學習:Symfony2框架學習筆記之HTTP Cache用法詳解》要點:
本文介紹了PHP學習:Symfony2框架學習筆記之HTTP Cache用法詳解,希望對您有用。如果有疑問,可以聯系我們。
PHP應用本文實例講述了Symfony2框架HTTP Cache用法.分享給大家供大家參考,具體如下:
PHP應用富web應用程序的本質意味著它們的動態(tài).無論你的應用程序多么有效率,每個哀求比起靜態(tài)文件來說總會存在很多的耗費.對于大多數web程序來說,這沒什么. Symfony2非常的輕快,無論你做些嚴重超載的哀求,每個哀求將會得到很快的回復,而不會對你的服務器造成壓力.但是隨著你站點的成長,負載將成為一個嚴重的問題.對每個哀求處理應該只被正常執(zhí)行一次.這就是緩存真正要達成的目標.
PHP應用站在巨人肩膀上的緩存:
PHP應用提高一個應用程序執(zhí)行效率的最有效方法是緩存一個頁面的所有輸出然后讓后續(xù)的哀求繞開整個應用程序.當然,這對于高動態(tài)性的站點來說并不是總是可能的.Symfony2 緩存系統(tǒng)是比較特別的,因為它依賴于在HTTP規(guī)范中定義的簡單強大的HTTP cache.沒有重新發(fā)明新的緩存方法,Symfony2 擁抱在web上定義基礎交流的標準.一旦你理解了基礎的HTTP校驗和過期緩存模式,你就會完全掌握了Symfony2的緩存系統(tǒng).
PHP應用第一步:一個網關緩存(gateway cache),或者反向代理.是一個坐在你應用程序前面的對立的層.反向代理緩存來自于你應用程序的響應并使用這些緩存響應在某些哀求到達你應用程序之前來回復它們. Symfony2提供了自己的反向代理,也可以使用其它任何的反向代理.
PHP應用第二步:HTTP緩存 (HTTP cache)頭用于和網關緩存以及任何其位于客戶和你的應用程序之間的其它緩存交流.Symfony2 提供了和緩存頭交互的預設行為和強大接口.
PHP應用第三步:HTTP 超時和校驗時用于決定一個緩存內容是否新鮮和陳舊的兩種模式.
PHP應用第四步:ESI(Edge Side Includes)允許HTTP緩存被用于獨立緩存頁面片段(甚至是嵌套片段).使用ESI,你甚至可以緩存一個完整的頁面60分鐘.但一個嵌入式邊欄緩存只有5分鐘.
PHP應用使用網關緩存
PHP應用當使用HTTP緩存時,緩存是跟你的應用程序完全分離的,它位于你的哀求客戶端和應用程序之間.該緩存的工作就是從客戶端接收哀求并把它們傳遞回你的應用程序.同時它也將接收從你的應用程序返回的響應并把它轉給客戶端.可以說它是你的應用程序和哀求客戶端之間哀求-響應交互的中間人.
PHP應用按照這個思路,緩存會保存被認為是“可緩存的”每一個響應回復.當同樣的哀求再次傳來時,該緩存會把自己緩存的響應直接回復給哀求客戶端,而完全忽略你的應用程序.這種類型的緩存就是HTTP網關緩存.目前有很多這類緩存,比如Varnish,Squid in reverse proxy mode和Symfony2 反向代理等.
PHP應用緩存類型
PHP應用一個網關緩存不是緩存的唯一類型.事實上,有三種不同類型的緩存會截獲并使用你的應用程序發(fā)出的HTTP緩存頭.它們是:
PHP應用瀏覽器緩存(Browser caches):瀏覽器擁有自己的本地緩存,這對你單擊"前一步"或者查看圖片和其它網絡資產時起到了主要作用.
PHP應用代理緩存(Proxy caches):一個代理緩存是一個多人位于一人之后的共享的緩存.它們大多是一些大公司或者ISP安裝用來減少延遲和網絡阻塞的.
PHP應用網關緩存(Gateway caches):像一個代理,也是一個共享緩存但是是位于服務器端的.一般是網絡管理員安裝它們,它使得網站更具可伸縮性,可靠性和高效性.網關緩存有時候被稱為反向代理緩存,代理緩存,更或者是HTTP加速器.
PHP應用Symfony2 反向代理
PHP應用Symfony2擁有一個用PHP編寫的反向代理(也叫做網關緩存).開啟它后,來自你應用程序的可緩存的響應回復將會開始被立刻緩存.安裝它相也當容易.每一個新的Symfony2應用程序都有一個預配置緩存內核(AppCache)包含了一個默認的AppKernel.該緩存內核就是個反向代理.要開啟緩存,修改前端控制器代碼使用緩存內核:
PHP應用
// web/app.php
require_once __DIR__.'/../app/bootstrap.php.cache';
require_once __DIR__.'/../app/AppKernel.php';
require_once __DIR__.'/../app/AppCache.php';
use Symfony\Component\HttpFoundation\Request;
$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
//使用AppCache包裹默認的AppKernel
$kernel = new AppCache($kernel);
$kernel->handle(Request::createFromGlobale())->send();
PHP應用緩存內核會立刻扮演一個反向代理的角色,緩存來自你應用程序的回復把它們發(fā)回給哀求客戶端.
PHP應用注意,該緩存內核有一個特別的getLog()辦法返回一個能夠表示在緩存層發(fā)生了什么的字符串.
PHP應用可以在開發(fā)環(huán)境中來調試和校驗你的緩存策略.
PHP應用
error_log($kernel->getLog());
PHP應用AppCache 對象是一個合理的默認配置,當然你也可以通過重寫getOptions()辦法來設置可選項對它進行調優(yōu).
PHP應用
// app/AppCache.php
use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache;
class AppCache extends HttpCache
{
protected function getOptions()
{
return array(
'debug' => false,
'default_ttl' => 0,
'private_headers' => array('Authorization', 'Cookie'),
'allow_reload' => false,
'allow_revalidate' => false,
'stale_while_revalidate' => 2,
'stale_if_error' => 60,
);
}
}
PHP應用注意,這里無論怎么重寫getOptions()辦法,其中debug選項將被包裹的AppKernel的debug值自動設置.
PHP應用下面是一些重要的可選項:
PHP應用default_ttl: 當沒有顯式的刷新信息在回復中提供時,一個緩沖實體應該被認為是新鮮的時間秒數.顯式的設置Cache-Control 或者 Expires 頭會覆蓋這個參數值.默認值為0.
private_headers:哀求頭組,它在回復上觸發(fā)"private" Cache-Control 行為,無論回復是通過Cache-Control 指令顯式的聲明是public還是private .默認為Authorization和Cookie.
allow_reload: 指定是否允許客戶端通過在哀求中指定Cache-Control的"no-cache"指令來強迫緩存重新加載.設置它為true時符合RFC2616規(guī)范.默認值為false.
allow_revalidate:指定是否允許客戶端通過在哀求中指定Cache-Control的"max-age=0"指令來強迫緩存重新校驗.設置它為true時符合RFC2616規(guī)范.默認值為false.
stale_while_revalidate:用于指定一個默認秒數(間隔是秒因為回復TTL精度是1秒),在期間緩存還在后臺進行重新校驗時可以立刻返回一個陳舊的回復(默認是2);該設置會被stale-while-revalidate HTTP Cache-Control擴展重寫(RFC 5861).
stale_if_error: 指定一個默認秒數(間隔是秒)在這期間緩存可以提供一個陳舊的回復當遇到一個錯誤時.默認值為60.該設置會被stale-if-error HTTP Cache-Contorl 擴展重寫(RFC5861)
PHP應用如果debug設置為true,Symfony2 會自動添加一個X-Symfony-Cache 頭到回復保存著關于緩存點擊和丟失的信息.
PHP應用從一個反向代理到另一個的轉換:
PHP應用Symfony2反向代理是一個在開發(fā)你的站點或者部署你的站點到一個共享主機而你無法安裝任何除PHP代碼以外的東西時的非常有用的工具.但是因為使用PHP編寫,它不能跟用C寫成的反向代理那樣快速.這就是為什么我們推薦使用Varnish或者Squid到你的運營服務器上的原因.好消息是從一個代理服務器到另外一個替換很容易,簡單的不用你修改任何程序代碼.你可以開始時使用Symfony2的反向代理等到了阻塞增加時升級到Varnish.
PHP應用注意:Symfony2 反向代理執(zhí)行效率獨立于應用程序的復雜性.因為應用程序核心僅僅在哀求需要被轉發(fā)到它時才被啟動.
PHP應用HTTP緩存說明:
PHP應用為了發(fā)揮可用緩存層的優(yōu)勢,你的應用程序必須能傳達它的哪個回復可以被緩存,什么時候/怎樣 緩存會變成陳舊的規(guī)則.這些是通過在回復(response)上設置HTTP 緩存頭來實現的.
PHP應用記住,"HTTP"只不過是一種web客戶端和服務器之間交流的簡單文本語言.當我們說HTTP 緩存時,我們說的是它允許客戶端和服務器交換信息相關的緩存.
PHP應用HTTP指定了4個Response緩存頭,我們需要關注一下:
PHP應用Cache-Control
Expires
ETag
Last-Modified
PHP應用其中最重要的也是萬能的頭是Cache-Control頭,它其實是一個各種緩存信息的集合.
PHP應用Cache-Control Header
PHP應用Cache-Control頭是唯一的一個其內部包含了各種各樣的關于一個response是否可以被緩存的信息.每條信息之間用逗號隔開.
PHP應用
Cache-Control:private,max-age=0,must-revalidate
Cache-Control:max-age=3600,must-revalidate
PHP應用Symfony 提供一個Cache-Control頭的抽象,使它的創(chuàng)建更加可控.
PHP應用
$response = new Response();
// 標記response為public還是private
$response->setPublic();
$response->setPrivate();
// 設置private或者shared 的最大年齡 age
$response->setMaxAge(600);
$response->setSharedMaxAge(600);
// 設置一個自定義的Cache-Control 指令
$response->headers->addCacheControlDirective('must-revalidate', true);
PHP應用公共vs私有 Response
PHP應用網關緩存和代理緩存都被認為是“共享”緩存,因為它們緩存的內容是被多用戶共享的.如果一個特定用戶的回復曾被錯誤的存儲到共享緩存中,它以后可能被返回給無數的不用用戶.想象一下,如果你的賬戶信息被緩存然后返回給每一個后來哀求他們自己賬戶頁面的用戶.要處理這種情況,每個回復可能都要設置時public還是private.
PHP應用public 說明給回復可能被private和共享的緩存保存.
private 說明所有的或者部分的回復信息時給一個單獨用戶的,所以不能緩存到共享緩存中.
PHP應用Symfony 謹慎地默認每個回復為private. 要使用共享緩存的優(yōu)點(比如Symfony2反向代理),回復必須被顯式的設置為public.
PHP應用平安方法:
PHP應用HTTP緩存僅僅為安全方法工作(比如GET和HEAD).要安全意味著當它為某個哀求服務時從來不會改變服務器上應用程序的狀態(tài).(當然你可以寫日志信息,緩存數據等).這里有兩個很合理的后果(consequences):
PHP應用當你的應用程序回復一個GET或者HEAD哀求時,你絕對不會改變你應用程序的狀態(tài).即使你不用網關緩存,代理緩存的存在意味著任何GET和HEAD哀求可能會或者可能不會真的達到你的服務器.
PHP應用不要期望PUT,POST或者DELETE方法被緩存.這些方法被使用意味著你應用程序狀態(tài)的改變.緩存它們將阻止某種哀求訪問或者改變你的應用程序.
PHP應用緩存規(guī)則和默認設置
PHP應用HTTP 1.1 默認情況下允許緩存任何事情除非有一個顯式的Cache-Control頭.實踐中,大多數緩存當哀求有cookie,一個授權頭,使用一個非安全的方法(比如PUT,POST,DELETE)或者當哀求有一個重定向代碼時,不會進行任何緩存活動.
PHP應用當開發(fā)者沒有做任何設置時,Symfony2 會自動依照下面的規(guī)則設置一個合理的比較保守的Cache-Control頭:
PHP應用如果沒有緩存頭被定義(Cache-Control,Expires,ETag 或者Last-Modified),Cache-Control被設置為no-cache,意味著該response將不會被緩存.
PHP應用如果Cache-Control 為空(但是有另一個緩存頭存在),它的值被設置為private,must-revalidate;
PHP應用如果至少一個Cache-Control指令被設置,并且沒有'public'或者‘private'指令被顯式的添加,Symfony2 會自動添加一個private指令(除去s-maxage 被設置的情況).
PHP應用HTTP過期和校驗
PHP應用HTTP規(guī)范定義了兩個緩存模型:
過期模型,你只需要通過包含一個Cache-Control和/或者一個Expires頭來指定一個Response應該多長時間被考慮“新鮮”問題.緩存理解過期將不再讓相同的哀求回復,直到緩存的版本達到它過期時間成為“stale"陳舊.
PHP應用校驗模型,當頁面時真正的動態(tài)頁面時(他們的展現經常變化),校驗模型就經常需要了.這種模型,緩存存儲response,但是要求服務對每個哀求是否緩存response依然進行校驗.
PHP應用應用程序使用唯一的response 標示符(ETag 頭) 和/或者 時間戳(Last-Modified 頭)來檢查頁面自從被緩存后是否放生了變化.
PHP應用這兩個模型的目標是通過依靠一個緩存存儲并返回"新鮮" response,使得應用程序從不生成相同的response兩次.
PHP應用過期:
PHP應用過期模型是在這兩個模型中是更加有效和簡單明確的模型,它應該在任何時候都有被使用的可能.當一個response使用一過期方式被緩存,緩存將存儲response并為哀求直接返回它而不去訪問應用程序,直到它過期.
PHP應用過期模型可以被熟練的使用一兩個,幾乎相同的,HTTP頭:比如 Expires或cache - control.
PHP應用過期和Expires 頭
PHP應用根據HTTP規(guī)范,Expires頭字段提供一個日期/時間,過了這個日期或時間后它的response就被認為是陳舊的了.Expires頭可以被Response的setExpires()辦法設置.它要求一個DateTime實例作為輸入參數.
PHP應用
$date = new DateTime();
$date->modify('+600 seconds');
$response->setExpires($date);
PHP應用生成的HTTP頭的結果如下:
PHP應用
Expires: Thu, 01 Mar 2011 16:00:00 GMT
PHP應用注意,因為規(guī)范的需要setExprise()辦法會自動把日期轉換為GMT時區(qū).
PHP應用我們注意到在HTTP規(guī)范1.1版之前,源服務不需要發(fā)送一個Date頭. 因此緩存(比如瀏覽器)可能需要依靠它本地的始終來評估Expires頭,造成計算生命周期時時鐘偏差. Expires頭的另一個限制是規(guī)范規(guī)定:"HTTP/1.1服務不應該發(fā)送Expires日期未來超過一年."
PHP應用過期和Cache-Control 頭
PHP應用因為Expires頭的限制,大多時候,你應該采用Cache-Control頭來替代它.回想一下,Cache-Control頭是用來指定多個不同緩存指令的.對于過期來說,有兩個指令,max-age 和 s-maxage.第一個被所有的緩存使用,然而第二個僅僅被用于共享緩存.
PHP應用
// 設置一個秒數,過了這個秒數后response就被認為是陳舊的了.
$response->setMaxAge(600);
// 同上,但是只用于共享緩存.
$response->setSharedMaxAge(600);
Cache-Control頭將使用如下格式(它可能還有其它指令):
Cache-Control: max-age=600, s-maxage=600
PHP應用校驗:
PHP應用一旦底層數據發(fā)生變化需要立刻對緩存資源進行更新時,過期模型就顯得力不從心了.在過期模型下,應用程序不會被要求返回更新的response直到緩存最后過期變?yōu)殛惻f內容以后.
PHP應用校驗模型解決了這個問題.在校驗模型下,緩存持續(xù)保存response.不同的是,對每一個哀求request,緩存都詢問應用程序緩存的response是否依然有效.如果緩存仍然有效,你的應用程序應該返回一個304狀態(tài)碼和一個空內容.這告訴緩存它可以為哀求用戶返回它緩存的response.
PHP應用在這個模型下,你主要節(jié)省了帶寬因為描述不會發(fā)送兩次到相同的客戶端(而是發(fā)送一個304回復代替).但是,如果你仔細設計你的應用程序,你可能能忍受304 response需要的最小數據并節(jié)省CPU.
PHP應用304狀態(tài)碼意味著沒有修改.它很重要因為它沒有包含整整的被哀求內容,而只是一個輕量級的導向集,它告訴緩存它應該使用它現在保存的版本回復哀求.跟過期類似,也有兩個不同的HTTP頭可以被用來實現校驗模型: ETag和Last-Modifed
PHP應用校驗和ETag頭
PHP應用ETag頭是一個字符串(也叫"entity-tag")它是目標資源一個表現的唯一標識.它完全由你的應用程序來生成和設置. 比如,如果 /about 資源被緩存保存時取決于日期和你應用程序的返回內容.一個ETag像一個手印,被用來快速的比較一個資源的兩個不同版本是否等效.
像手印,同一個資源的所有表示形式中每個ETag必須是唯一的.讓我們來簡單實現一個生成ETag使用md5加密的回復內容作為內容:
PHP應用
public function indexAction()
{
$response = $this->render('MyBundle:Main:index.html.twig');
$response->setETag(md5($response->getContent()));
$response->isNotModified($this->getRequest());
return $response;
}
PHP應用Response::isNotModified()辦法把和Request一起發(fā)送的ETag與Response上的ETag進行比較.如果兩個匹配,辦法自動設置Response狀態(tài)碼為304.
PHP應用這個算法非常簡單也非常通用,但是你需要在能計算ETag之前創(chuàng)建一個完整的Response,校驗模型是次優(yōu)選擇.換句話說,它節(jié)省了帶寬,單沒有節(jié)省CPU利用.??
PHP應用Symfony2還通過向setETag()辦法傳入true作為第二個參數,來支持弱ETag.
PHP應用校驗和Last-Modified 頭
PHP應用Last-Modified頭是校驗模型的第二種形式.根據HTTP規(guī)范,”Last-Modified 頭字段指定日期和時間,在這個時間源服務器相信該表現是最后被修改版.“
換句話說,應用程序決定基于自動緩存內容被緩存后是否被更新過來判斷緩存的內容是否要被更新過.舉個例子,你可以使用最新更新日期為所有需要計算資源表現的對象作為Last-Modified頭的值:
PHP應用
public function showAction($articleSlug)
{
//...
$articleDate = new \DateTime($article->getUdateAt());
$authorDate = new \DateTime($author->getUpdateAt());\
$date = $authorDate>$articleDate ? $authorDate : $articleDate;
$response->setLastModified($date);
$response->isNotModified($this->getRequest());
return $response;
}
PHP應用Response::isNotModified() 方法比較哀求Request中的If-Modified-Since頭和Response中的Last-Modified 頭.如果他們相等,Response會被設置一個304狀態(tài)碼.
PHP應用注意,If-Modified-since 哀求頭等于最終發(fā)送到客戶端特定資源Last-Modified頭.這就是如何客戶端和服務端相互交流決定資源自從它被緩存后是否被更新.
PHP應用使用校驗優(yōu)化你的代碼:
PHP應用任何緩存策略的主要目的都是減輕應用程序的加載.換句話說,你的應用程序做的越少來返回304 response,越好.Response::isNotModified()辦法通過暴露一個簡單有效的模式做到了.
PHP應用
public funcation showAction($articleSlug)
{
//獲取最小信息來計算ETag或者Last-Modified值(基于Request,數據是從數據庫或者一個鍵值對存儲實例中獲取.
$article = //...
//創(chuàng)建一個Response帶有一個ETag 和/或者 一個Last-Modified 頭
$response = new Response();
$response->setETag($article->computeETag());
$response->setLastModified($article->getPublishedAt());
//為給定的Request檢查Response沒有被修改
if($response->isNotModified($this->getRequest())){
//立刻返回304 Response
return $response;
}else{
//做一些更多的工作-比如獲取更多的數據
$comment=//...
//或者用你已經開啟的$response渲染一個模版
return $this->render('MyBundle:MyController:article.html.twig',
array('article'=>$article, 'comments' =>$comments),
$response
);
}
}
PHP應用當Response沒有被修改后,isNotModified()自動設置response的狀態(tài)碼為304,移除response的內容,移除一些不需要為304存在的頭.
PHP應用不同的回復響應:
PHP應用到目前為止,我們已經假設了每個URI只有一個目標資源的表示.默認情況下,HTTP緩存通過使用URI的資源作為緩存鍵被執(zhí)行.如果兩個人哀求同一個可緩存資源的URI,第二個用戶將獲取緩存版本.有時候這些不夠,不同版本的用一個URI需要被按照一個或者多個哀求頭的值來被緩存.舉個例子,如果當客戶端支持你壓縮頁面時,任何給定的URI都有兩種表示:一個是客戶端支持壓縮時,一個是不支持時的表示.這時候哀求頭的Accept-Encoding值將決定使用哪個.
PHP應用在這種情況下,我們需要回復的特定URI緩存一個壓縮版本和一個非壓縮版本,基于哀求的Accept-Encoding值返回它們.這是通過Vary Response頭,Vary是一個不同頭用逗號分隔,它的值觸發(fā)哀求資源的不同表示.
PHP應用
Vary:Accept-Encoding,User-Agent
PHP應用注意,這個特別的Vary頭,將基于URI和Accept-Encoding和User-Agent 哀求頭為每個資源的不同版本進行緩存.
PHP應用Response對象提供一個干凈的接口來管理Vary 頭:
PHP應用
// 設置一個vary 頭
$response->setVary('Accept-Encoding');
// 設置多個vary頭
$response->setVary(array('Accept-Encoding', 'User-Agent'));
PHP應用setVary()辦法需要一個頭名字或者一個頭名字數組對應不同的response.
PHP應用過期和校驗:
PHP應用你當然可以在同一個Response中同時使用校驗和過期.因為過期勝過校驗,你可以輕易的從它們兩個中根據好處做出選擇.換句話說,通過同時使用過期和校驗,你可以指示緩存服務于緩存的內容,同時后臺間隔檢查來調查內容是否依然合法.
PHP應用更多Response辦法:
PHP應用Response類提供了許多和緩存相關的辦法.下面是主要的一些:
PHP應用
// 標志Response過期陳舊
$response->expire();
// 強迫response返回一個適合 304 的沒有內容的response
$response->setNotModified();
PHP應用另外,跟緩存最相關的HTTP頭可以被通過一個單獨的辦法setCache()設置.
PHP應用
// 通過一個調用設置緩存參數
$response->setCache(array(
'etag' => $etag,
'last_modified' => $date,
'max_age' => 10,
's_maxage' => 10,
'public' => true,
// 'private' => true,
));
PHP應用使用ESI(Edge Side Includes)
PHP應用網關緩存是一個提高你網站執(zhí)行效率的很好的途徑.但是它們有一個限制:只能緩存整個頁面.如果你不想緩存整個頁面或者頁面的某一部分很動態(tài),你就沒那么幸運了.
PHP應用幸運的是,Symfony2為這些情況提供一個辦理方案,基于ESI技術.它允許頁面指定的部分和主頁比起來有一個不同的緩存策略.
PHP應用ESI規(guī)范描述標簽你可以嵌入到你的頁面來和網關緩存交流.Symfony2中只實現了一個標簽,include, 因為這是唯一一個能在Akami上下文之外使用的標簽.
PHP應用
<html>
<body>
Some content
<!-- 嵌入一個其它頁的內容 -->
<esi:include src="http://..." />
More content
</body>
</html>
PHP應用從這個例子中注意到每個ESI標簽有一個全限定URL.一個ESI標簽表示可以通過一個給定的URL獲取的一個頁面片段.
PHP應用當哀求被處理時,網關緩存從它的緩存或者從背后的應用程序中哀求回復獲取整個頁面.換句話說,網關緩存既從緩存中獲取包含的頁面片段也會再次從背后的應用程序中獲取回復哀求的頁面片段.當所有的ESI標簽被解析后,網關緩存合并每一個ESI內容到一個主頁并返回最后的內容到客戶端.所有的這一切都透明的發(fā)生在網關緩存級(在你的程序外).你將看到,如果你選擇ESI標簽,Symfony2讓這包含它們的這一過程幾乎不費勁.
PHP應用在Symfony2中使用ESI
PHP應用首先,使用ESI需要確認在你的應用程序配置中已經打開.
PHP應用YAML格式:
PHP應用
# app/config/config.yml
framework:
# ...
esi: { enabled: true }
PHP應用XML格式:
PHP應用
<!-- app/config/config.xml -->
<framework:config ...>
<!-- ... -->
<framework:esi enabled="true" />
</framework:config>
PHP應用PHP代碼格式:
PHP應用
// app/config/config.php
$container->loadFromExtension('framework', array(
// ...
'esi' => array('enabled' => true),
));
PHP應用現在假設我們有一個頁面時相對靜態(tài)的,除了一個新聞自動收報機在內容的底部.使用ESI,我們可以緩存新聞自動收報機獨立于頁面其它部分.
PHP應用
public function indexAction()
{
$response = $this->render('MyBundle:MyController:index.html.twig');
$response->setSharedMaxAge(600);
return $response;
}
PHP應用在該示例中,我們給全頁面緩存周期為10分鐘.接下來,通過嵌入一個action讓新聞ticker包含到模板中.這是通過render贊助來實現的.因為嵌入的內容來自其它頁面,Symfony2使用一個標準的render贊助來配置ESI標簽:
PHP應用Twig格式:
PHP應用
{% render '...:news' with {}, {'standalone': true} %}
PHP應用PHP格式:
PHP應用
<?php echo $view['actions']->render('...:news', array(), array('standalone' => true)) ?>
PHP應用通過把standalone設置為true,告訴Symfony2這個action應該被渲染為一個ESI標簽.
PHP應用你可能想知道為什么要使用一個helper辦法來代替直接寫ESI標簽.這是因為使用helper讓你的應用程序工作即使沒有網關緩存被安裝.讓我們來看看它是怎樣工作的.
PHP應用當standalone為false時(也是默認值),Symfony2在發(fā)送response到客戶端之前合并包含的頁面內容到一個主頁.
PHP應用但是當standalone為true時,并且如果Symfony2發(fā)現它跟支持ESI的網關緩存對話時,它生成一個ESI include標簽.
PHP應用如果沒有網關緩存或者網關緩存不支持ESI,Symfony2將只合并包含的標簽頁面內容到一個主要的像它在standalone為false時所做的一樣.
PHP應用嵌入的action現在可以指定自己的緩存規(guī)則了,完全獨立于主頁.
PHP應用
public function newsAction()
{
//...
$response->setShareMaxAge(60);
}
PHP應用使用ESI,整個頁面緩存將被保持600秒有效,但是新聞組建緩存將只持續(xù)60秒.
PHP應用ESI的一個必備條件是嵌入的action可以通過一個URL被拜訪,這樣網關緩存才可以獨立于頁面其它部分獲取它.當然,一個action不能被通過一個URL拜訪除非有一個路由指向它.Symfony2 通過一個通用的路由和controller負責這個.
PHP應用為了ESI包含標簽能正常的工作,你必須定義_internal 路由:
PHP應用YAML格式:
PHP應用
# app/config/routing.yml
_internal:
resource: "@FrameworkBundle/Resources/config/routing/internal.xml"
prefix: /_internal
PHP應用XML格式:
PHP應用
<!-- app/config/routing.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
<import resource="@FrameworkBundle/Resources/config/routing/internal.xml" prefix="/_internal" />
</routes>
PHP應用PHP代碼格式:
PHP應用
// app/config/routing.php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
$collection->addCollection($loader->import('@FrameworkBundle/Resources/config/routing/internal.xml', '/_internal'));
return $collection;
PHP應用因為路由允許所有的action通過一個URL被拜訪,你可以通過使用Symfony2防火墻(允許拜訪你的反向代理的IP范圍)內容保護它.
PHP應用緩存策略的一大優(yōu)勢是你可以讓你的應用程序根據動態(tài)的需要同時又盡量的減少觸及應用程序.
PHP應用一旦你開始使用ESI,請記住一定使用s-maxage指令代替max-age.因為瀏覽器只接受聚合的資源,它不知道子組件,所以它會依照max-age指令緩存整個頁面.這是你不希望它做的.
PHP應用render helper支持的兩外兩個有用選項:
alt:用作ESI標簽的alt屬性,當src找不到時,它允許你指定一個替代URL.
ignore_errors:如果設置為true,一個onerror屬性將被添加到ESI,并且屬性值設置為continue,在一個失敗露件中,網關緩存將只默默的移除ESI標簽.
PHP應用緩存失效:
PHP應用“計算機科學中有兩大難題:緩存失效和命名事物”---Phil Karlton
PHP應用你永遠都不需要失效緩存數據,因為失效早已在HTTP緩存模型中被考慮到了.如果你使用校驗,你永遠都不需要通過定義校驗任何事情;如果你使用過期并失效某個資源,它意味著你設置一個未來的過期日期.因為在任何類型的反向代理中失效都是一個頂級規(guī)范,如果你不擔心失效,你可以在不改變任何應用程序代碼的情況下在反向代理間切換.
PHP應用其實,所有的反向代理都提供了清除緩存數據的方式,但是你需要盡量的避免使用它們.最標準的清除給定URL的緩存的方式是通過指定哀求的HTTP方法為PURGE 來進行.
PHP應用下面是如何配置Symfony2的反向代理支持PURGE HTTP辦法:
PHP應用
// app/AppCache.php
use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache;
class AppCache extends HttpCache
{
protected function invalidate(Request $request)
{
if ('PURGE' !== $request->getMethod()) {
return parent::invalidate($request);
}
$response = new Response();
if (!$this->getStore()->purge($request->getUri())) {
$response->setStatusCode(404, 'Not purged');
} else {
$response->setStatusCode(200, 'Purged');
}
return $response;
}
}
PHP應用注意,你必須保護你的PURGE HTTP辦法以避免隨便一個人使用某些辦法清除你的緩存數據.
PHP應用總結:
PHP應用Symfony2旨在遵循一條被證明了的道路規(guī)則:HTTP. 緩存也不例外.掌握Symfony2緩存系統(tǒng)意味著熟悉HTTP緩存模式和有效的使用它們.
PHP應用這就意味著,你不能只依賴于symfony2文檔和代碼示例,你必須了解有關HTTP緩存和網關緩存的更寬闊的知識,比如Varnish.
PHP應用希望本文所述對大家基于Symfony框架的PHP程序設計有所贊助.
歡迎參與《PHP學習:Symfony2框架學習筆記之HTTP Cache用法詳解》討論,分享您的想法,維易PHP學院為您提供專業(yè)教程。
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/7315.html