-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
clean up cache invalidation information on the cache chapter #4626
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d4d2236
2bddbb1
979034a
0accf63
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -328,7 +328,14 @@ its creation more manageable:: | |
// set a custom Cache-Control directive | ||
$response->headers->addCacheControlDirective('must-revalidate', true); | ||
|
||
Public vs private Responses | ||
.. tip:: | ||
|
||
If you need to set cache headers for many different controller actions, | ||
you might want to look into the FOSHttpCacheBundle_. It provides a way | ||
to define cache headers based on the URL pattern and other request | ||
properties. | ||
|
||
Public vs Private Responses | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Both gateway and proxy caches are considered "shared" caches as the cached | ||
|
@@ -393,9 +400,10 @@ header when none is set by the developer by following these rules: | |
``private`` directive automatically (except when ``s-maxage`` is set). | ||
|
||
.. _http-expiration-validation: | ||
.. _http-expiration-and-validation: | ||
|
||
HTTP Expiration and Validation | ||
------------------------------ | ||
HTTP Expiration, Validation and Invalidation | ||
-------------------------------------------- | ||
|
||
The HTTP specification defines two caching models: | ||
|
||
|
@@ -412,7 +420,9 @@ The HTTP specification defines two caching models: | |
header) to check if the page has changed since being cached. | ||
|
||
The goal of both models is to never generate the same response twice by relying | ||
on a cache to store and return "fresh" responses. | ||
on a cache to store and return "fresh" responses. To achieve long caching times | ||
but still provide updated content immediately, *cache invalidation* is | ||
sometimes used. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. afaik invalidation is not described in the HTTP 1.1 spec so i just append this here rather than in the two models above. |
||
|
||
.. sidebar:: Reading the HTTP Specification | ||
|
||
|
@@ -766,7 +776,7 @@ at some interval (the expiration) to verify that the content is still valid. | |
annotations. See the `FrameworkExtraBundle documentation`_. | ||
|
||
.. index:: | ||
pair: Cache; Configuration | ||
pair: Cache; Configuration | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be reverted. We always use four spaces for indentation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i was looking at other files. http_fundamentals.rst for example is aligning on |
||
|
||
More Response Methods | ||
~~~~~~~~~~~~~~~~~~~~~ | ||
|
@@ -794,8 +804,110 @@ Additionally, most cache-related HTTP headers can be set via the single | |
)); | ||
|
||
.. index:: | ||
single: Cache; ESI | ||
single: ESI | ||
single: Cache; Invalidation | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a fourth space before the text? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i would like to keep it consistent with the rest of the doc where we seem to use 3 spaces for the indexes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, indeed, we are not really consistent here. |
||
|
||
.. _http-cache-invalidation: | ||
|
||
Cache Invalidation | ||
~~~~~~~~~~~~~~~~~~ | ||
|
||
"There are only two hard things in Computer Science: cache invalidation | ||
and naming things." -- Phil Karlton | ||
|
||
Once an URL is cached by a gateway cache, the cache will not ask the | ||
application for that content anymore. This allows the cache to provide fast | ||
responses and reduces the load on your application. However, you risk | ||
delivering outdated content. A way out of this dilemma is to use long | ||
cache lifetimes, but to actively notify the gateway cache when content | ||
changes. Reverse proxies usually provide a channel to receive such | ||
notifications, typically through special HTTP requests. | ||
|
||
.. caution:: | ||
|
||
While cache invalidation is powerful, avoid it when possible. If you fail | ||
to invalidate something, outdated caches will be served for a potentially | ||
long time. Instead, use short cache lifetimes or use the validation model, | ||
and adjust your controllers to perform efficient validation checks as | ||
explained in :ref:`optimizing-cache-validation`. | ||
|
||
Furthermore, since invalidation is a topic specific to each type of reverse | ||
proxy, using this concept will tie you to a specific reverse proxy or need | ||
additional efforts to support different proxies. | ||
|
||
Sometimes, however, you need that extra performance you can get when | ||
explicitly invalidating. For invalidation, your application needs to detect | ||
when content changes and tell the cache to remove the URLs which contain | ||
that data from its cache. | ||
|
||
.. tip:: | ||
|
||
If you want to use cache invalidation, have a look at the | ||
`FOSHttpCacheBundle`_. This bundle provides services to help with various | ||
cache invalidation concepts, and also documents the configuration for the | ||
a couple of common caching proxies. | ||
|
||
If one content corresponds to one URL, the ``PURGE`` model works well. | ||
You send a request to the cache proxy with the HTTP method ``PURGE`` (using | ||
the word "PURGE" is a convention, technically this can be any string) instead | ||
of ``GET`` and make the cache proxy detect this and remove the data from the | ||
cache instead of going to Symfony to get a response. | ||
|
||
Here is how you can configure the Symfony reverse proxy to support the | ||
``PURGE`` HTTP method:: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we add a note that technically you could rename purge to any string? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added. but not sure its a good idea, its adding more information |
||
|
||
// app/AppCache.php | ||
|
||
// ... | ||
use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache; | ||
use Symfony\Component\HttpFoundation\Request; | ||
use Symfony\Component\HttpFoundation\Response; | ||
|
||
class AppCache extends HttpCache | ||
{ | ||
protected function invalidate(Request $request, $catch = false) | ||
{ | ||
if ('PURGE' !== $request->getMethod()) { | ||
return parent::invalidate($request, $catch); | ||
} | ||
|
||
if ('127.0.0.1' !== $request->getClientIp()) { | ||
return new Response('Invalid HTTP method', Response::HTTP_BAD_REQUEST); | ||
} | ||
|
||
$response = new Response(); | ||
if ($this->getStore()->purge($request->getUri())) { | ||
$response->setStatusCode(200, 'Purged'); | ||
} else { | ||
$response->setStatusCode(200, 'Not found'); | ||
} | ||
|
||
return $response; | ||
} | ||
} | ||
|
||
.. caution:: | ||
|
||
You must protect the ``PURGE`` HTTP method somehow to avoid random people | ||
purging your cached data. | ||
|
||
**Purge** instructs the cache to drop a resource in *all its variants* | ||
(according to the ``Vary`` header, see above). An alternative to purging is | ||
**refreshing** a content. Refreshing means that the caching proxy is | ||
instructed to discard its local cache and fetch the content again. This way, | ||
the new content is already available in the cache. The drawback of refreshing | ||
is that variants are not invalidated. | ||
|
||
In many applications, the same content bit is used on various pages with | ||
different URLs. More flexible concepts exist for those cases: | ||
|
||
* **Banning** invalidates responses matching regular expressions on the | ||
URL or other criteria; | ||
* **Cache tagging** lets you add a tag for each content used in a response | ||
so that you can invalidate all URLs containing a certain content. | ||
|
||
.. index:: | ||
single: Cache; ESI | ||
single: ESI | ||
|
||
.. _edge-side-includes: | ||
|
||
|
@@ -1040,67 +1152,6 @@ The ``render_esi`` helper supports two other useful options: | |
to the ESI with a value of ``continue`` indicating that, in the event of | ||
a failure, the gateway cache will simply remove the ESI tag silently. | ||
|
||
.. index:: | ||
single: Cache; Invalidation | ||
|
||
.. _http-cache-invalidation: | ||
|
||
Cache Invalidation | ||
------------------ | ||
|
||
"There are only two hard things in Computer Science: cache invalidation | ||
and naming things." -- Phil Karlton | ||
|
||
You should never need to invalidate cached data because invalidation is already | ||
taken into account natively in the HTTP cache models. If you use validation, | ||
you never need to invalidate anything by definition; and if you use expiration | ||
and need to invalidate a resource, it means that you set the expires date | ||
too far away in the future. | ||
|
||
.. note:: | ||
|
||
Since invalidation is a topic specific to each type of reverse proxy, | ||
if you don't worry about invalidation, you can switch between reverse | ||
proxies without changing anything in your application code. | ||
|
||
Actually, all reverse proxies provide ways to purge cached data, but you | ||
should avoid them as much as possible. The most standard way is to purge the | ||
cache for a given URL by requesting it with the special ``PURGE`` HTTP method. | ||
|
||
Here is how you can configure the Symfony reverse proxy to support the | ||
``PURGE`` HTTP method:: | ||
|
||
// app/AppCache.php | ||
|
||
// ... | ||
use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache; | ||
use Symfony\Component\HttpFoundation\Request; | ||
use Symfony\Component\HttpFoundation\Response; | ||
|
||
class AppCache extends HttpCache | ||
{ | ||
protected function invalidate(Request $request, $catch = false) | ||
{ | ||
if ('PURGE' !== $request->getMethod()) { | ||
return parent::invalidate($request, $catch); | ||
} | ||
|
||
$response = new Response(); | ||
if ($this->getStore()->purge($request->getUri())) { | ||
$response->setStatusCode(200, 'Purged'); | ||
} else { | ||
$response->setStatusCode(404, 'Not purged'); | ||
} | ||
|
||
return $response; | ||
} | ||
} | ||
|
||
.. caution:: | ||
|
||
You must protect the ``PURGE`` HTTP method somehow to avoid random people | ||
purging your cached data. | ||
|
||
Summary | ||
------- | ||
|
||
|
@@ -1128,3 +1179,4 @@ Learn more from the Cookbook | |
.. _`P6 - Caching: Browser and intermediary caches`: http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache | ||
.. _`FrameworkExtraBundle documentation`: http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/cache.html | ||
.. _`ESI`: http://www.w3.org/TR/esi-lang | ||
.. _`FOSHttpCacheBundle`: http://foshttpcachebundle.readthedocs.org/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok to change this section title?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, as long as you make it BC. (so adding a
.. _http-expiration-and-validation:
anchorThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did that. looks a bit funny with the double anchor, however.