Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use HTTP Cache in Symfony2

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly shows you "how to use HTTP Cache in Symfony2", the content is easy to understand, clear, hope to help you solve doubts, the following let the editor lead you to study and learn "how to use HTTP Cache in Symfony2" this article.

The details are as follows:

The nature of rich web applications means that they are dynamic. No matter how efficient your application is, each request will always be more expensive than a static file. For most web programs, this is fine. Symfony2 is very brisk, and no matter you make some seriously overloaded requests, each request will be answered quickly without putting pressure on your server. But as your site grows, load will become a serious problem. Processing of each request should be performed normally only once. This is what the cache really wants to achieve.

A cache standing on the shoulder of a giant:

The most effective way to improve the execution efficiency of an application is to cache all the output of a page and then allow subsequent requests to 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 the simple and powerful HTTP cache defined in the HTTP specification. Instead of reinventing a new caching method, Symfony2 embraces the standard that defines basic communication on web. Once you understand the basic HTTP checksum expiration caching mode, you will have a complete grasp of Symfony2's caching system.

Step 1: a gateway cache (gateway cache), or reverse proxy. It's an opposing layer sitting in front of your application. 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, and you can use any other reverse proxy.

Step 2: the HTTP cache (HTTP cache) header is used to communicate with the gateway cache and any other cache it is located between the customer and your application. Symfony2 provides preset behavior and powerful interfaces for interacting with cache headers.

Step 3: HTTP timeouts and checktimes are used to determine whether a cache content is fresh or obsolete.

Step 4: ESI (Edge Side Includes) allows HTTP caching to be used to independently cache page fragments (or even nested fragments). With ESI, you can even cache a complete page for 60 minutes. But an embedded sidebar cache lasts only 5 minutes.

Use gateway cach

When using HTTP caching, caching is completely separate from your application and is located between your requesting client and your application. The job of the cache is to receive requests from the client and pass them back to your application. At the same time, it will receive the response returned from your application and transfer it to the client. It can be said to be the middleman of request-response interaction between your application and the requesting client.

According to this idea, the cache holds every response that is considered "cacheable". When the same request comes again, the cache will reply its own cached response directly to the requesting client, ignoring your application completely. 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 proxies.

Cache Typ

A gateway cache is not the only type of cache. In fact, there are three different types of caches that intercept and use HTTP cache headers issued by your application. They are:

Browser caching (Browser caches): browsers have their own local cache, which plays a major role when you click "previous" or view pictures and other web assets.

Proxy cache (Proxy caches): a proxy cache is a shared cache with multiple people behind one person. Most of them are installed by large companies or ISP to reduce latency and network congestion.

Gateway cache (Gateway caches): like a proxy, it is also a shared cache but is located on the server side. They are usually installed by network administrators, which make websites more scalable, reliable and efficient. Gateway caching is sometimes referred to as reverse proxy cache, proxy cache, or HTTP accelerator.

Symfony2 reverse proxy

Symfony2 has a reverse proxy (also known as gateway cache) written in PHP. Once it is turned on, cacheable responses from your application will start to be cached immediately. It should also be easy to install. Every new Symfony2 application has a preconfigured caching kernel (AppCache) that contains a default AppKernel. The cache kernel is a reverse proxy. To enable caching, modify the front-end controller code to use the caching kernel:

/ / web/app.phprequire_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 (); / / use AppCache to wrap the default AppKernel$kernel = new AppCache ($kernel); $kernel- > handle (Request::createFromGlobale ())-> send ()

The cache kernel immediately acts as a reverse proxy, caching responses 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, but you can also tune it optionally by overriding the getOptions () method.

/ / app/AppCache.phpuse 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,);}}

Note that no matter how you override the getOptions () method here, the debug option will automatically set the debug value of the wrapped AppKernel.

Here are some important options:

Default_ttl: when no explicit refresh information is provided in the reply, a buffer entity should be considered the number of seconds of fresh time. Explicitly setting the Cache-Control or Expires header overrides this parameter value. The default value is 0.

Private_headers: request header group, which triggers the "private" Cache-Control action on the reply, regardless of whether the reply is explicitly declared as public or private through the Cache-Control instruction. The default is Authorization and Cookie.

Allow_reload: specifies whether to allow the client to force the cache to reload by specifying the "no-cache" instruction of Cache-Control in the request. It conforms to the RFC2616 specification when it is set to true. The default is false.

Allow_revalidate: specifies whether to allow the client to force cache revalidation by specifying the "max-age=0" instruction of Cache-Control in the request. It conforms to the RFC2616 specification when it is set to true. The default is false.

Stale_while_revalidate: used to specify a default number of seconds (the interval is seconds because the reply TTL precision is 1 second), during which the cache can immediately return an old reply (default is 2) when the cache is still rechecked in the background (default is 2); this setting will be overwritten by the stale-while-revalidate HTTP Cache-Control extension (RFC 5861).

Stale_if_error: specify a default number of seconds (interval is seconds) during which the cache can provide a stale reply when an error is encountered. The default value is 60. This setting will be overridden by the stale-if-error HTTP Cache-Contorl extension (RFC5861)

If debug is set to true,Symfony2, a X-Symfony-Cache header is automatically added to the reply to save information about cached clicks and losses.

Conversion from one reverse proxy to another:

Symfony2 reverse proxy is a very useful tool when developing your site or deploying your site to a shared host and you can't install anything other than PHP code. But because it's written in PHP, it can't be as fast as a reverse proxy written in C. This is why we recommend using Varnish or Squid to your operating server. The good news is that it's easy to replace from one proxy server to another, simply without you modifying any program code. You can start by using the reverse proxy of Symfony2 and upgrade to Varnish when the blocking increases.

Note: the efficiency of Symfony2 reverse proxy execution is independent of the complexity of the application. Because the application core is started only when the request needs to be forwarded to it.

HTTP cache description:

To take advantage of the available cache layers, your application must be able to communicate which of its responses can be cached and when / how caching will become an outdated rule. This is achieved by setting the HTTP cache header on the response.

Remember, "HTTP" is just a simple text language for communication between web clients and servers. When we talk about HTTP caching, we are talking about it allowing clients and servers to exchange caches related to information.

HTTP specifies four Response cache headers, which we need to pay attention to:

Cache-Control

Expires

ETag

Last-Modified

The most important and versatile header is the Cache-Control header, which is actually a collection of cached information.

Cache-Control Header

The Cache-Control header is the only one that contains all kinds of information about whether an response can be cached. Each message is separated by a comma.

Cache-Control:private,max-age=0,must-revalidateCache-Control:max-age=3600,must-revalidate

Symfony provides an abstraction of Cache-Control headers, making its creation more manageable.

Response = new Response (); / / Mark whether response is public or private$response- > setPublic (); $response- > setPrivate (); / / set the maximum age of private or shared age$response- > setMaxAge; $response- > setSharedMaxAge (600); / / set a custom Cache-Control directive $response- > headers- > addCacheControlDirective ('must-revalidate', true)

Public vs Private Response

Both the gateway cache and the proxy cache are considered "shared" caches because the content they cache is shared by multiple users. If a particular user's reply has been mistakenly stored in the shared cache, it may later be returned to countless unused users. Imagine if your account information was cached and returned to every user who later requested their own account page. To handle this situation, each reply may have to be set when public or private.

Public notes that the reply may be cached by private and shared.

Private indicates that all or part of the reply message is given to a single user, so it cannot be cached in the shared cache.

Symfony carefully defaults to private for each reply. To use the advantages of shared caching (such as Symfony2 reverse proxy), the reply must be explicitly set to public.

Security methods:

HTTP caching only works for secure methods (such as GET and HEAD). Being secure means that when it serves a request, it never changes the state of the application on the server. (of course you can write log messages, cache data, etc.). Here are two reasonable consequences:

When your application responds to a GET or HEAD request, you will never change the state of your application. Even if you don't use gateway caching, the presence of proxy caching means that any GET and HEAD requests may or may not actually reach your server.

Do not expect PUT,POST or DELETE methods to be cached. The use of these methods means changes in the state of your application. Caching them will prevent some request to access or change your application.

Cache rules and default settin

HTTP 1.1 by default allows anything to be cached unless there is an explicit Cache-Control header. In practice, most caches do not perform any caching activity when the request has cookie, an authorization header, using an insecure method (such as PUT,POST,DELETE), or when the request has a redirect code.

When the developer does not make any settings, Symfony2 will automatically set a reasonable and conservative Cache-Control header according to the following rules:

If no cache header is defined (Cache-Control,Expires,ETag or Last-Modified), Cache-Control is set to no-cache, which means that the response will not be cached.

If Cache-Control is empty (but another cache header exists), its value is set to private,must-revalidate

If at least one Cache-Control instruction is set and no 'public' or' private' instruction is explicitly added, Symfony2 automatically adds a private instruction (excluding the case where s-maxage is set).

HTTP expiration and check

The HTTP specification defines two caching models:

In the out-of-date model, you only need to specify how long a Response should be considered "fresh" by including a Cache-Control and / or an Expires header. Cache understanding expiration will no longer allow the same request to be answered until the cached version reaches its expiration time and becomes "stale" obsolete.

Validation models are often needed when pages are really dynamic pages (their presentation often changes). In this model, the cache stores the response, but requires the service to verify whether the response is cached for each request.

The application uses a unique response identifier (ETag header) and / or timestamp (Last-Modified header) to check whether the page has been released since it was cached.

The goal of these two models is to make the application never generate the same response twice by relying on a cache to store and return "fresh" response.

Expired:

The out-of-date model is the more effective and simple model in these two models, and it should be used at any time. When a response is cached using an expiration method, the cache stores the response and returns it directly for the request without accessing the application until it expires.

Expired models can be skillfully used with one or two, almost the same HTTP headers: such as Expires or cache-control.

Expiration and Expires header

According to the HTTP specification, the Expires header field provides a date / time after which its response is considered stale. The Expires header can be set by the setExpires () method of Response. It requires an instance of DateTime as an input parameter.

$date = new DateTime (); $date- > modify ('+ 600seconds'); $response- > setExpires ($date)

The result of the generated HTTP header is as follows:

Expires: Thu, 01 Mar 2011 16:00:00 GMT

Note that because the specification requires the setExprise () method to automatically convert the date to the GMT time zone.

We note that prior to version 1.1 of the HTTP specification, the source service did not need to send a Date header. So a cache (such as a browser) may need to rely on its local always to evaluate the Expires header, resulting in clock skew when calculating the life cycle. Another limitation of the Expires header is the specification that states: "HTTP/1.1 services should not send Expires dates for more than a year in the future."

Expiration and Cache-Control header

Because of the limitation of Expires headers, you should use Cache-Control headers instead of it most of the time. Recall that the Cache-Control header is used to specify several different cache instructions. For expiration, there are two instructions, max-age and s-maxage. The first is used by all caches, while the second is used only for shared caches.

/ / set the number of seconds after which response is considered obsolete. $response- > setMaxAge (600); / / same as above, but only for shared cache. $response- > setSharedMaxAge; the Cache-Control header will use the following format (it may have other instructions): Cache-Control: max-age=600, s-maxage=600

Check:

Once the underlying data changes and the cache resources need to be updated immediately, the expiration model appears to be inadequate. Under the expiration model, applications are not required to return updated response until the cache finally expires and becomes obsolete.

The verification model solves this problem. Under the check model, the cache persists the response. The difference is that for each request request, the cache asks whether the application's cached response is still valid. If the cache is still valid, your application should return a 304 status code and an empty content. This tells the cache that it can return its cached response for the requesting user.

In this model, you mainly save bandwidth because the description is not sent to the same client twice (instead of sending a 304 reply). However, if you design your application carefully, you may be able to tolerate the minimum data required by 304 response and save CPU.

The 304 status code means that there is no modification. It is important because it does not contain the entire requested content, but only a lightweight guide set, and it tells the cache that it should reply to the request with the version it now saves. Similar to expiration, there are two different HTTP headers that can be used to implement the verification model: ETag and Last-Modifed

Checksum Etag header

The ETag header is a string (also called "entity-tag") that uniquely identifies a representation of the target resource. It is generated and set entirely by your application. For example, if the / about resource is cached, it depends on the date and the return content of your application. An ETag, like a handprint, is used to quickly compare whether two different versions of a resource are equivalent.

Like handprints, each ETag must be unique in all representations of the same resource. Let's simply implement a reply that generates ETag using md5 encryption as content:

Public function indexAction () {$response = $this- > render ('MyBundle:Main:index.html.twig'); $response- > setETag (md5 ($response- > getContent ()); $response- > isNotModified ($this- > getRequest ()); return $response;}

The Response::isNotModified () method compares the ETag sent with Request with the ETag on Response. If the two match, the method automatically sets the Response status code to 304.

This algorithm is very simple and versatile, but you need to create a complete Response before you can calculate the ETag, and the check model is the second best choice. In other words, it saves bandwidth, not CPU utilization alone.

Symfony2 also supports weak ETag by passing true as the second parameter to the setETag () method.

Checksum Last-Modified header

The Last-Modified header is the second form of the verification model. According to the HTTP specification, "the Last-Modified header field specifies the date and time at which the source server believes the performance is the last modified version."

In other words, the application determines whether the cached content is to be updated based on whether the automatically cached content is updated or not. For example, you can use the latest update date as the value of the Last-Modified header for all objects that need to calculate resource representation:

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;}

The Response::isNotModified () method compares the If-Modified-Since header in the request Request with the Last-Modified header in Response. If they are equal, the Response will be set to a 304 status code.

Notice that the If-Modified-since request header is equal to the Last-Modified header that is finally sent to the client-specific resource. This is how the client and server communicate with each other to determine whether the resource has been updated since it has been cached.

Use validation to optimize your code:

The main purpose of any caching strategy is to ease the loading of the application. In other words, the less your application does to return 304 response, the better. The Response::isNotModified () method does this by exposing a simple and effective pattern.

Public funcation showAction ($articleSlug) {/ / gets the minimum information to calculate the ETag or Last-Modified value (based on Request, the data is obtained from the database or a key-value pair storage instance. $article = / /... / / create a Response with an ETag and / or a Last-Modified header $response = new Response (); $response- > setETag ($article- > computeETag ()); $response- > setLastModified ($article- > getPublishedAt ()); / / check that Response has not been modified if ($response- > isNotModified ($this- > getRequest ()) for the given Request) {/ / return 304Response return $response immediately } else {/ / do some more work-such as getting more data $comment=//... / / or rendering a template return $this- > render with the $response you have already opened ('MyBundle:MyController:article.html.twig', array (' article'= > $article, 'comments' = > $comments), $response);}}

When the Response is not modified, isNotModified () automatically sets the status code of the response to 304, removes the contents of the response, and removes some headers that do not need to exist for 304.

Different responses:

So far, we have assumed that each URI has only one representation of the target resource. By default, HTTP caching is executed by using URI's resources as cache keys. If two people request a URI of the same cacheable resource, the second user will get the cached version. Sometimes these are not enough, different versions of a URI need to be cached according to the value of one or more request headers. For example, if the client supports you to compress the page, any given URI has two representations: one is when the client supports compression, and the other is when it doesn't. At this point, the Accept-Encoding value of the request header will determine which one to use.

In this case, we need to cache a compressed version and an uncompressed version of the specific URI we reply to, and return them based on the requested Accept-Encoding value. This is done through the Vary Response header, where Vary is a different header separated by a comma, and its value triggers different representations of the requested resource.

Vary:Accept-Encoding,User-Agent

Note that this particular Vary header will be cached for different versions of each resource based on URI and Accept-Encoding and User-Agent request headers.

The Response object provides a clean interface to manage Vary headers:

/ / set a vary header $response- > setVary ('Accept-Encoding'); / / set multiple vary headers $response- > setVary (array (' Accept-Encoding', 'User-Agent'))

The setVary () method requires a header name or an array of header names corresponding to a different response.

Expiration and check:

You can certainly use checksum expiration in the same Response at the same time. Because expiration is better than checking, you can easily choose between the two according to the benefits. In other words, by using both expiration and validation, you can instruct the cache to serve the cached content, while the background checks at intervals to investigate whether the content is still legal.

More Response methods:

The Response class provides a number of cache-related methods. Here are some of the main ones:

/ / Mark Response obsolete $response- > expire (); / / force response to return a content-free response$response- > setNotModified ()

In addition, the HTTP headers most relevant to the cache can be set through a separate method, setCache ().

/ / set the cache parameter $response- > setCache through a call ('etag' = > $etag,' last_modified' = > $date, 'max_age' = > 10,' public' = > true, / / 'private' = > true,))

Use ESI (Edge Side Includes)

Gateway caching is a good way to improve the execution efficiency of your website. But they have a limitation: they can only cache the entire page. If you don't want to cache the whole page or a part of the page that is dynamic, you're not so lucky.

Fortunately, Symfony2 provides a solution for these situations, based on ESI technology. It allows the specified part of the page to have a different caching strategy than the home page.

The ESI specification description tag you can embed into your page to communicate with the gateway cache. Only one tag, include, is implemented in Symfony2, because this is the only tag that can be used outside the context of Akami.

Some content More content

Notice from this example that each ESI tag has a fully qualified URL. An ESI tag represents a page fragment that can be obtained through a given URL.

When the request is processed, the gateway cache fetches the entire page from its cache or requests a reply from the application behind it. In other words, the gateway cache fetches both the contained page fragment from the cache and the page fragment replying to the request again from the application behind it. When all the ESI tags are parsed, the gateway cache merges each ESI content to a home page and returns the final content to the client. All of this happens transparently at the gateway cache level (outside your program). As you'll see, if you choose ESI tags, Symfony2 makes the process of including them almost effortless.

Using ESI in Symfony2

First of all, to use ESI, you need to make sure that it is turned on in your application configuration.

YAML format:

# app/config/config.ymlframework: #... Esi: {enabled: true}

XML format:

PHP code format:

/ / app/config/config.php$container- > loadFromExtension ('framework', array (/ /... 'esi' = > array (' enabled' = > true),)

Now suppose we have a page that is relatively static, except for a news automatic receiver at the bottom of the content. With ESI, we can cache the news automatic receiver independently of the rest of the page.

Public function indexAction () {$response = $this- > render ('MyBundle:MyController:index.html.twig'); $response- > setSharedMaxAge (600); return $response;}

In this example, we give the full page cache period of 10 minutes. Next, the news ticker is included in the template by embedding an action. This is done with the help of render. Because the embedded content comes from other pages, Symfony2 uses a standard render help to configure ESI tags:

Twig format:

{% render '...: news' with {}, {' standalone': true}%}

PHP format:

By setting standalone to true, tell Symfony2 that the action should be rendered as an ESI tag.

You may wonder why you use a helper method instead of writing ESI tags directly. This is because using helper makes your application work even if no gateway cache is installed. Let's see how it works.

When standalone is false (also the default), Symfony2 merges the page content into a master page before sending the response to the client.

But when standalone is true, and if Symfony2 finds that it is talking to a gateway cache that supports ESI, it generates an ESI include tag.

If there is no gateway cache or the gateway cache does not support ESI,Symfony2, only the included tag page content will be merged into a major one, as it does when standalone is false.

Embedded action can now specify its own caching rules, completely independent of the home page.

Public function newsAction () {/ /... $response- > setShareMaxAge (60);}

With ESI, the entire page cache will remain valid for 600 seconds, but the news build cache will last only 60 seconds.

A prerequisite for ESI is that the embedded action can be accessed through a URL so that the gateway cache can retrieve it independently of the rest of the page. Of course, an action cannot be accessed through an URL unless there is a route to it. Symfony2 is responsible for this through a general routing and controller.

In order for ESI including tags to work properly, you must define _ internal routes:

YAML format:

# app/config/routing.yml_internal: resource: "@ FrameworkBundle/Resources/config/routing/internal.xml" prefix: / _ internal

XML format:

PHP code format:

/ / app/config/routing.phpuse Symfony\ Component\ Routing\ RouteCollection;use Symfony\ Component\ Routing\ Route;$collection- > addCollection ($loader- > import ('@ FrameworkBundle/Resources/config/routing/internal.xml','/ _ internal')); return $collection

Because routing allows all action to be accessed through a URL, you can protect it by using Symfony2 Firewall (the IP scope that allows access to your reverse proxy).

One of the advantages of caching strategy is that you can allow your application to meet dynamic needs while minimizing access to the application.

Once you start using ESI, remember to use the s-maxage instruction instead of max-age. Because the browser only accepts aggregated resources, it doesn't know the subcomponents, so it caches the entire page according to the max-age instruction. That's what you don't want it to do.

There are two other useful options supported by render helper:

Alt: used as the alt attribute of the ESI tag, which allows you to specify an alternative URL when src cannot find it.

Ignore_errors: if set to true, an onerror attribute will be added to the ESI, and the attribute value will be set to continue. In a failed event, the gateway cache will only silently remove the ESI tag.

Cache invalidation:

"there are two difficult problems in computer science: cache invalidation and naming things"-Phil Karlton

You never need to cache data because invalidation is already taken into account in the HTTP caching model. If you use validation, you never need to verify anything by definition; if you use a resource that expires and expires, it means you set a future expiration date. Because failure in any type of reverse proxy is a top-level specification, if you are not worried about failure, you can switch between reverse proxies without changing any application code.

In fact, all reverse proxies provide a way to clear cached data, but you need to avoid using them as much as possible. The most standard way to clear the cache for a given URL is by specifying that the HTTP method of the request is PURGE.

Here is how to configure the reverse proxy for Symfony2 to support the PURGE HTTP method:

/ / app/AppCache.phpuse 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 } return $response;}}

Note that you must protect your PURGE HTTP methods from anyone using certain methods to erase your cached data.

The above is all the contents of the article "how to use HTTP Cache in Symfony2". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report