Home >Backend Development >PHP Tutorial >Detailed explanation of HTTP Cache usage in Symfony2 framework study notes, symfony2 study notes_PHP tutorial
The examples in this article describe the usage of Symfony2 framework HTTP Cache. Share it with everyone for your reference, the details are as follows:
The nature of rich web applications means they are dynamic. No matter how efficient your application is, there will always be a lot of cost per request compared to static files. For most web programs, this is fine. Symfony2 is very light and even if you do something seriously overloaded with requests, each request will be responded to very quickly without putting a strain on your server. But as your site grows, load will become a serious issue. Handling should only be performed normally once per request. This is what caching is really about.
Cache standing on the shoulders of giants:
The most effective way to improve the execution efficiency of an application is to cache all output of a page and then let subsequent requests bypass the entire application. Of course, this is not always possible for highly dynamic sites. The Symfony2 caching system is special because it relies on a simple and powerful HTTP cache defined in the HTTP specification. Rather than reinventing new caching methods, Symfony2 embraces the standards that define fundamental communication on the web. Once you understand the basics of HTTP checksums and expiration caching patterns, you will have a complete grasp of Symfony2's caching system.
Step one: a gateway cache, or reverse proxy. is an opposing layer that sits in front of your application. A reverse proxy caches responses from your application and uses these cached responses to reply to certain requests before they reach your application. Symfony2 provides its own reverse proxy, or you can use any other reverse proxy.
Step 2: The HTTP cache header is used to communicate with the gateway cache and any other caches between the client and your application. Symfony2 provides preset behaviors and a powerful interface for interacting with cache headers.
Step 3: HTTP timeout and verification are two modes used to determine whether a cached content is fresh or stale.
Step 4: ESI (Edge Side Includes) allows HTTP caching to be used to cache page fragments independently (even nested fragments). Using ESI, you can even cache a complete page for 60 minutes. But an embedded sidebar is only cached for 5 minutes.
Use gateway cache
When using HTTP caching, the cache is completely separate from your application and sits between your requesting client and your application. The cache's job is to receive requests from clients and pass them back to your application. It will also receive the response from your application and forward it to the client. It can be said to be the middleman of the request-response interaction between your application and the requesting client.
Following this idea, the cache will save every response that is considered "cacheable". When the same request comes again, the cache will reply its cached response directly to the requesting client, completely ignoring your application. This type of cache is the HTTP gateway cache. There are currently many such caches, such as Varnish, Squid in reverse proxy mode and Symfony2 reverse proxy.
Cache type
A gateway cache is not the only type of cache. In fact, there are three different types of caches that intercept and use the HTTP cache headers sent by your application. They are:
Browser caches: The browser has its own local cache, which plays a major role when you click "Previous" or view images and other web assets.
Proxy caches: A proxy cache is a shared cache that is located behind one person. They are mostly installed by large companies or ISPs to reduce latency and network congestion.
Gateway caches: Like a proxy, it is also a shared cache but located on the server side. Typically network administrators install them, and they make websites more scalable, reliable, and efficient. Gateway caches are sometimes called reverse proxy caches, proxy caches, or HTTP accelerators.
Symfony2 reverse proxy
Symfony2 has a reverse proxy (also called gateway cache) written in PHP. After turning it on, cacheable responses from your application will begin to be cached immediately. Installing it is also quite easy. Every new Symfony2 application has a preconfigured cache kernel (AppCache) containing a default AppKernel. The cache core is a reverse proxy. To enable caching, modify the front controller code to use the caching kernel:
// 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();
The caching kernel will immediately act as a reverse proxy, caching replies from your application and sending them back to the requesting client.
Note that the cache kernel has a special getLog() method that returns a string that represents what happened at the cache layer.
You can debug and verify your caching strategy in the development environment.
error_log($kernel->getLog());
The AppCache object is a reasonable default configuration. Of course, you can also set optional options to tune it by overriding the getOptions() method.
// 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, ); } }
注意,这里无论怎么重写getOptions()方法,其中debug选项将被包裹的AppKernel的debug值自动设置。
下面是一些重要的可选项:
default_ttl: 当没有显式的刷新信息在回复中提供时,一个缓冲实体应该被认为是新鲜的时间秒数。显式的设置Cache-Control 或者 Expires 头会覆盖这个参数值。默认值为0。
private_headers:请求头组,它在回复上触发"private" Cache-Control 行为,无论回复是通过Cache-Control 指令显式的声明是public还是private 。默认为Authorization和Cookie。
allow_reload: 指定是否允许客户端通过在请求中指定Cache-Control的"no-cache"指令来强迫缓存重新加载。设置它为true时符合RFC2616规范。默认值为false。
allow_revalidate:指定是否允许客户端通过在请求中指定Cache-Control的"max-age=0"指令来强迫缓存重新校验。设置它为true时符合RFC2616规范。默认值为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)
如果debug设置为true,Symfony2 会自动添加一个X-Symfony-Cache 头到回复保存着关于缓存点击和丢失的信息。
从一个反向代理到另一个的转换:
Symfony2反向代理是一个在开发你的站点或者部署你的站点到一个共享主机而你无法安装任何除PHP代码以外的东西时的非常有用的工具。但是因为使用PHP编写,它不能跟用C写成的反向代理那样快速。这就是为什么我们推荐使用Varnish或者Squid到你的运营服务器上的原因。好消息是从一个代理服务器到另外一个替换很容易,简单的不用你修改任何程序代码。你可以开始时使用Symfony2的反向代理等到了阻塞增加时升级到Varnish。
注意:Symfony2 反向代理执行效率独立于应用程序的复杂性。因为应用程序核心仅仅在请求需要被转发到它时才被启动。
HTTP缓存说明:
为了发挥可用缓存层的优势,你的应用程序必须能传达它的哪个回复可以被缓存,什么时候/怎样 缓存会变成陈旧的规则。这些是通过在回复(response)上设置HTTP 缓存头来实现的。
记住,"HTTP"只不过是一种web客户端和服务器之间交流的简单文本语言。当我们说HTTP 缓存时,我们说的是它允许客户端和服务器交换信息相关的缓存。
HTTP指定了4个Response缓存头,我们需要关注一下:
Cache-Control
Expires
ETag
Last-Modified
其中最重要的也是万能的头是Cache-Control头,它其实是一个各种缓存信息的集合。
Cache-Control Header
Cache-Control头是唯一的一个其内部包含了各种各样的关于一个response是否可以被缓存的信息。每条信息之间用逗号隔开。
Cache-Control:private,max-age=0,must-revalidate Cache-Control:max-age=3600,must-revalidate
Symfony 提供一个Cache-Control头的抽象,使它的创建更加可控。
$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);
公共vs私有 Response
网关缓存和代理缓存都被认为是“共享”缓存,因为它们缓存的内容是被多用户共享的。如果一个特定用户的回复曾被错误的存储到共享缓存中,它以后可能被返回给无数的不用用户。想象一下,如果你的账户信息被缓存然后返回给每一个后来请求他们自己账户页面的用户。要处理这种情况,每个回复可能都要设置时public还是private。
public 说明给回复可能被private和共享的缓存保存。
private 说明所有的或者部分的回复信息时给一个单独用户的,所以不能缓存到共享缓存中。
Symfony 谨慎地默认每个回复为private。 要使用共享缓存的优点(比如Symfony2反向代理),回复必须被显式的设置为public。
安全方法:
HTTP缓存仅仅为安全方法工作(比如GET和HEAD)。要安全意味着当它为某个请求服务时从来不会改变服务器上应用程序的状态。(当然你可以写日志信息,缓存数据等)。这里有两个很合理的后果(consequences):
当你的应用程序回复一个GET或者HEAD请求时,你绝对不会改变你应用程序的状态。即使你不用网关缓存,代理缓存的存在意味着任何GET和HEAD请求可能会或者可能不会真的达到你的服务器。
不要期望PUT,POST或者DELETE方法被缓存。这些方法被使用意味着你应用程序状态的改变。缓存它们将阻止某种请求访问或者改变你的应用程序。
缓存规则和默认设置
HTTP 1.1 默认情况下允许缓存任何事情除非有一个显式的Cache-Control头。实践中,大多数缓存当请求有cookie,一个授权头,使用一个非安全的方法(比如PUT,POST,DELETE)或者当请求有一个重定向代码时,不会进行任何缓存活动。
当开发者没有做任何设置时,Symfony2 会自动按照下面的规则设置一个合理的比较保守的Cache-Control头:
如果没有缓存头被定义(Cache-Control,Expires,ETag 或者Last-Modified),Cache-Control被设置为no-cache,意味着该response将不会被缓存。
如果Cache-Control 为空(但是有另一个缓存头存在),它的值被设置为private,must-revalidate;
如果至少一个Cache-Control指令被设置,并且没有'public'或者‘private'指令被显式的添加,Symfony2 会自动添加一个private指令(除去s-maxage 被设置的情况)。
HTTP过期和校验
HTTP规范定义了两个缓存模型:
过期模型,你只需要通过包含一个Cache-Control和/或者一个Expires头来指定一个Response应该多长时间被考虑“新鲜”问题。缓存理解过期将不再让相同的请求回复,直到缓存的版本达到它过期时间成为“stale"陈旧。
校验模型,当页面时真正的动态页面时(他们的展现经常变化),校验模型就经常需要了。这种模型,缓存存储response,但是要求服务对每个请求是否缓存response依然进行校验。
应用程序使用唯一的response 标示符(ETag 头) 和/或者 时间戳(Last-Modified 头)来检查页面自从被缓存后是否放生了变化。
这两个模型的目标是通过依靠一个缓存存储并返回"新鲜" response,使得应用程序从不生成相同的response两次。
过期:
过期模型是在这两个模型中是更加有效和简单明确的模型,它应该在任何时候都有被使用的可能。当一个response使用一过期方式被缓存,缓存将存储response并为请求直接返回它而不去访问应用程序,直到它过期。
过期模型可以被熟练的使用一两个,几乎相同的,HTTP头:比如 Expires或cache - control。
过期和Expires 头
根据HTTP规范,Expires头字段提供一个日期/时间,过了这个日期或时间后它的response就被认为是陈旧的了。Expires头可以被Response的setExpires()方法设置。它要求一个DateTime实例作为输入参数。
$date = new DateTime(); $date->modify('+600 seconds'); $response->setExpires($date);
生成的HTTP头的结果如下:
Expires: Thu, 01 Mar 2011 16:00:00 GMT
注意,因为规范的需要setExprise()方法会自动把日期转换为GMT时区。
我们注意到在HTTP规范1.1版之前,源服务不需要发送一个Date头。 因此缓存(比如浏览器)可能需要依靠它本地的始终来评估Expires头,造成计算生命周期时时钟偏差。 Expires头的另一个限制是规范规定:"HTTP/1.1服务不应该发送Expires日期未来超过一年。"
过期和Cache-Control 头
因为Expires头的限制,大多时候,你应该采用Cache-Control头来替代它。回想一下,Cache-Control头是用来指定多个不同缓存指令的。对于过期来说,有两个指令,max-age 和 s-maxage。第一个被所有的缓存使用,然而第二个仅仅被用于共享缓存。
// 设置一个秒数,过了这个秒数后response就被认为是陈旧的了。 $response->setMaxAge(600); // 同上,但是只用于共享缓存。 $response->setSharedMaxAge(600); Cache-Control头将使用如下格式(它可能还有其它指令): Cache-Control: max-age=600, s-maxage=600
校验:
一旦底层数据发生变化需要立刻对缓存资源进行更新时,过期模型就显得力不从心了。在过期模型下,应用程序不会被要求返回更新的response直到缓存最后过期变为陈旧内容以后。
校验模型解决了这个问题。在校验模型下,缓存持续保存response。不同的是,对每一个请求request,缓存都询问应用程序缓存的response是否依然有效。如果缓存仍然有效,你的应用程序应该返回一个304状态码和一个空内容。这告诉缓存它可以为请求用户返回它缓存的response。
在这个模型下,你主要节省了带宽因为描述不会发送两次到相同的客户端(而是发送一个304回复代替)。但是,如果你仔细设计你的应用程序,你可能能忍受304 response需要的最小数据并节省CPU。
304状态码意味着没有修改。它很重要因为它没有包含整整的被请求内容,而只是一个轻量级的导向集,它告诉缓存它应该使用它现在保存的版本回复请求。跟过期类似,也有两个不同的HTTP头可以被用来实现校验模型: ETag和Last-Modifed
校验和ETag头
ETag头是一个字符串(也叫"entity-tag")它是目标资源一个表现的唯一标识。它完全由你的应用程序来生成和设置。 比如,如果 /about 资源被缓存保存时取决于日期和你应用程序的返回内容。一个ETag像一个手印,被用来快速的比较一个资源的两个不同版本是否等效。
像手印,同一个资源的所有表示形式中每个ETag必须是唯一的。让我们来简单实现一个生成ETag使用md5加密的回复内容作为内容:
public function indexAction() { $response = $this->render('MyBundle:Main:index.html.twig'); $response->setETag(md5($response->getContent())); $response->isNotModified($this->getRequest()); return $response; }
Response::isNotModified()方法把和Request一起发送的ETag与Response上的ETag进行比较。如果两个匹配,方法自动设置Response状态码为304。
这个算法非常简单也非常通用,但是你需要在能计算ETag之前创建一个完整的Response,校验模型是次优选择。换句话说,它节省了带宽,单没有节省CPU利用。
Symfony2还通过向setETag()方法传入true作为第二个参数,来支持弱ETag。
校验和Last-Modified 头
Last-Modified头是校验模型的第二种形式。根据HTTP规范,”Last-Modified 头字段指定日期和时间,在这个时间源服务器相信该表现是最后被修改版。“
换句话说,应用程序决定基于自动缓存内容被缓存后是否被更新过来判断缓存的内容是否要被更新过。举个例子,你可以使用最新更新日期为所有需要计算资源表现的对象作为Last-Modified头的值:
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; }
Response::isNotModified() 方法比较请求Request中的If-Modified-Since头和Response中的Last-Modified 头。如果他们相等,Response会被设置一个304状态码。
注意,If-Modified-since 请求头等于最终发送到客户端特定资源Last-Modified头。这就是如何客户端和服务端相互交流决定资源自从它被缓存后是否被更新。
使用校验优化你的代码:
任何缓存策略的主要目的都是减轻应用程序的加载。换句话说,你的应用程序做的越少来返回304 response,越好。Response::isNotModified()方法通过暴露一个简单有效的模式做到了。
public funcation showAction($articleSlug) { //获取最小信息来计算ETag或者Last-Modified值(基于Request,数据是从数据库或者一个键值对存储实例中获取。 $article = //... //创建一个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 ); } }
当Response没有被修改后,isNotModified()自动设置response的状态码为304,移除response的内容,移除一些不需要为304存在的头。
不同的回复响应:
到目前为止,我们已经假设了每个URI只有一个目标资源的表示。默认情况下,HTTP缓存通过使用URI的资源作为缓存键被执行。如果两个人请求同一个可缓存资源的URI,第二个用户将获取缓存版本。有时候这些不够,不同版本的用一个URI需要被按照一个或者多个请求头的值来被缓存。举个例子,如果当客户端支持你压缩页面时,任何给定的URI都有两种表示:一个是客户端支持压缩时,一个是不支持时的表示。这时候请求头的Accept-Encoding值将决定使用哪个。
在这种情况下,我们需要回复的特定URI缓存一个压缩版本和一个非压缩版本,基于请求的Accept-Encoding值返回它们。这是通过Vary Response头,Vary是一个不同头用逗号分隔,它的值触发请求资源的不同表示。
Vary:Accept-Encoding,User-Agent
注意,这个特别的Vary头,将基于URI和Accept-Encoding和User-Agent 请求头为每个资源的不同版本进行缓存。
Response对象提供一个干净的接口来管理Vary 头:
// 设置一个vary 头 $response->setVary('Accept-Encoding'); // 设置多个vary头 $response->setVary(array('Accept-Encoding', 'User-Agent'));
setVary()方法需要一个头名字或者一个头名字数组对应不同的response。
过期和校验:
你当然可以在同一个Response中同时使用校验和过期。因为过期胜过校验,你可以轻易的从它们两个中根据好处做出选择。换句话说,通过同时使用过期和校验,你可以指示缓存服务于缓存的内容,同时后台间隔检查来调查内容是否依然合法。
更多Response方法:
Response类提供了许多和缓存相关的方法。下面是主要的一些:
// 标志Response过期陈旧 $response->expire(); // 强迫response返回一个适合 304 的没有内容的response $response->setNotModified();
另外,跟缓存最相关的HTTP头可以被通过一个单独的方法setCache()设置。
// 通过一个调用设置缓存参数 $response->setCache(array( 'etag' => $etag, 'last_modified' => $date, 'max_age' => 10, 's_maxage' => 10, 'public' => true, // 'private' => true, ));
使用ESI(Edge Side Includes)
网关缓存是一个提高你网站执行效率的很好的途径。但是它们有一个限制:只能缓存整个页面。如果你不想缓存整个页面或者页面的某一部分很动态,你就没那么幸运了。
幸运的是,Symfony2为这些情况提供一个解决方案,基于ESI技术。它允许页面指定的部分和主页比起来有一个不同的缓存策略。
ESI规范描述标签你可以嵌入到你的页面来和网关缓存交流。Symfony2中只实现了一个标签,include, 因为这是唯一一个能在Akami上下文之外使用的标签。
<html> <body> Some content <!-- 嵌入一个其它页的内容 --> <esi:include src="http://..." /> More content </body> </html>
从这个例子中注意到每个ESI标签有一个全限定URL。一个ESI标签表示可以通过一个给定的URL获取的一个页面片段。
当请求被处理时,网关缓存从它的缓存或者从背后的应用程序中请求回复获取整个页面。换句话说,网关缓存既从缓存中获取包含的页面片段也会再次从背后的应用程序中获取回复请求的页面片段。当所有的ESI标签被解析后,网关缓存合并每一个ESI内容到一个主页并返回最后的内容到客户端。所有的这一切都透明的发生在网关缓存级(在你的程序外)。你将看到,如果你选择ESI标签,Symfony2让这包含它们的这一过程几乎不费劲。
在Symfony2中使用ESI
首先,使用ESI需要确认在你的应用程序配置中已经打开。
YAML格式:
# app/config/config.yml framework: # ... esi: { enabled: true }
XML格式:
<!-- app/config/config.xml --> <framework:config ...> <!-- ... --> <framework:esi enabled="true" /> </framework:config>
PHP代码格式:
// app/config/config.php $container->loadFromExtension('framework', array( // ... 'esi' => array('enabled' => true), ));
现在假设我们有一个页面时相对静态的,除了一个新闻自动收报机在内容的底部。使用ESI,我们可以缓存新闻自动收报机独立于页面其它部分。
public function indexAction() { $response = $this->render('MyBundle:MyController:index.html.twig'); $response->setSharedMaxAge(600); return $response; }
在该示例中,我们给全页面缓存周期为10分钟。接下来,通过嵌入一个action让新闻ticker包含到模板中。这是通过render帮助来实现的。因为嵌入的内容来自其它页面,Symfony2使用一个标准的render帮助来配置ESI标签:
Twig格式:
{% render '...:news' with {}, {'standalone': true} %}
PHP格式:
<?php echo $view['actions']->render('...:news', array(), array('standalone' => true)) ?>
通过把standalone设置为true,告诉Symfony2这个action应该被渲染为一个ESI标签。
你可能想知道为什么要使用一个helper方法来代替直接写ESI标签。这是因为使用helper让你的应用程序工作即使没有网关缓存被安装。让我们来看看它是怎样工作的。
当standalone为false时(也是默认值),Symfony2在发送response到客户端之前合并包含的页面内容到一个主页。
但是当standalone为true时,并且如果Symfony2发现它跟支持ESI的网关缓存对话时,它生成一个ESI include标签。
如果没有网关缓存或者网关缓存不支持ESI,Symfony2将只合并包含的标签页面内容到一个主要的像它在standalone为false时所做的一样。
嵌入的action现在可以指定自己的缓存规则了,完全独立于主页。
public function newsAction() { //... $response->setShareMaxAge(60); }
使用ESI,整个页面缓存将被保持600秒有效,但是新闻组建缓存将只持续60秒。
ESI的一个必备条件是嵌入的action可以通过一个URL被访问,这样网关缓存才可以独立于页面其它部分获取它。当然,一个action不能被通过一个URL访问除非有一个路由指向它。Symfony2 通过一个通用的路由和controller负责这个。
为了ESI包含标签能正常的工作,你必须定义_internal 路由:
YAML格式:
# app/config/routing.yml _internal: resource: "@FrameworkBundle/Resources/config/routing/internal.xml" prefix: /_internal
XML格式:
<!-- 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代码格式:
// 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;
因为路由允许所有的action通过一个URL被访问,你可以通过使用Symfony2防火墙(允许访问你的反向代理的IP范围)内容保护它。
缓存策略的一大优势是你可以让你的应用程序根据动态的需要同时又尽量的减少触及应用程序。
一旦你开始使用ESI,请记住一定使用s-maxage指令代替max-age。因为浏览器只接受聚合的资源,它不知道子组件,所以它会按照max-age指令缓存整个页面。这是你不希望它做的。
render helper支持的两外两个有用选项:
alt:用作ESI标签的alt属性,当src找不到时,它允许你指定一个替代URL。
ignore_errors:如果设置为true,一个onerror属性将被添加到ESI,并且属性值设置为continue,在一个失败事件中,网关缓存将只默默的移除ESI标签。
缓存失效:
“计算机科学中有两大难题:缓存失效和命名事物”---Phil Karlton
你永远都不需要失效缓存数据,因为失效早已在HTTP缓存模型中被考虑到了。如果你使用校验,你永远都不需要通过定义校验任何事情;如果你使用过期并失效某个资源,它意味着你设置一个未来的过期日期。因为在任何类型的反向代理中失效都是一个顶级规范,如果你不担心失效,你可以在不改变任何应用程序代码的情况下在反向代理间切换。
其实,所有的反向代理都提供了清除缓存数据的方式,但是你需要尽量的避免使用它们。最标准的清除给定URL的缓存的方式是通过指定请求的HTTP方法为PURGE 来进行。
下面是如何配置Symfony2的反向代理支持PURGE HTTP方法:
// 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; } }
注意,你必须保护你的PURGE HTTP方法以避免随便一个人使用某些方法清除你的缓存数据。
总结:
Symfony2旨在遵循一条被证明了的道路规则:HTTP。 缓存也不例外。掌握Symfony2缓存系统意味着熟悉HTTP缓存模式和有效的使用它们。
这就意味着,你不能只依赖于symfony2文档和代码示例,你必须了解有关HTTP缓存和网关缓存的更宽阔的知识,比如Varnish。
希望本文所述对大家基于Symfony框架的PHP程序设计有所帮助。