Symfony2 Framework Learning Notes HTTP cache usage detailed _php instance

Source: Internet
Author: User
Tags gmt time zone varnish
This example describes the Symfony2 framework HTTP cache usage. Share to everyone for your reference, as follows:

The nature of rich Web applications means their dynamics. No matter how efficient your application is, there is always a lot of cost to each request than a static file. For most Web applications, this is nothing. Symfony2 is very brisk, and no matter how heavily overloaded you are, every request will get a quick response without stress on your server. But as your site grows, the load will become a serious problem. The processing of each request should be performed only once. This is what the cache really wants to achieve.

The cache standing on the shoulders of giants:

The most effective way to improve the efficiency of an application is to cache all the output of a page and then let subsequent requests bypass the entire application. Of course, this is not always possible for high-dynamic sites. The Symfony2 cache system is more specific because it relies on the simple and powerful HTTP cache defined in the HTTP specification. Without reinventing the new caching method, Symfony2 embraced the criteria for defining basic communication on the Web. Once you understand the underlying HTTP checksum expiration cache mode, you will have complete control over the Symfony2 cache system.

The first step: a gateway cache, or a reverse proxy. is an opposing layer sitting in front of your application. The reverse proxy caches the responses from your application and uses these cached responses to reply to some requests before they reach your application. SYMFONY2 provides its own reverse proxy, or it can use any other reverse proxy.

Step two: The HTTP cache header is used to communicate with the gateway cache and any other caches that are located between the client and your application. SYMFONY2 provides the default behavior and powerful interfaces for interacting with the cache header.

The third step: HTTP timeouts and checksums are used to determine whether a cached content is fresh or stale in two modes.

Fourth step: ESI (Edge Side includes) allows the HTTP cache to be used to cache page fragments (even nested fragments) independently. With ESI, you can even cache a full page for 60 minutes. But an embedded sidebar cache is only 5 minutes.

Using the gateway Cache

When using the HTTP cache, the cache is completely detached from your application and is located between your requesting client and the application. The job of the cache is to receive requests from clients and pass them back to your application. It will also receive the response returned from your application and transfer it to the client. It can be said that it is the intermediary between your application and the request-response interaction between the requesting client.

In this way, the cache saves every response that is thought to be "cacheable". When the same request comes again, the cache responds directly to the requesting client with its cached response, ignoring your application completely. This type of cache is the HTTP gateway cache. There are many such caches, such as varnish,squid in reverse proxy mode and SYMFONY2 reverse proxy.

Cache type

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

Browser cache (Browser caches): The browser has its own local cache, which plays a major role when you click "Previous" or view pictures and other network assets.

Proxy caches: A proxy cache is a shared cache of multiple people after one person. Most of them are large companies or ISPs installed to reduce latency and network congestion.

Gateway caches: Like a proxy, it is also a shared cache but is located on the server side. Typically, network administrators install them, which makes the site more scalable, reliable, and efficient. Gateway caches are sometimes referred to as reverse proxy caches, proxy caches, or HTTP accelerators.

SYMFONY2 Reverse Proxy

Symfony2 has a reverse proxy (also known as a gateway cache) written in PHP. When it is turned on, a cached response from your application will begin to be cached immediately. It is also easy to install it. Each new Symfony2 application has a pre-configured cache kernel (AppCache) that contains a default appkernel. The cache core is a reverse proxy. To turn on caching, modify the front controller code to use the cache 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 package default Appkernel$kernel = new AppCache ($kernel); $kernel->handle (Request:: Createfromglobale ())->send ();

The cache kernel immediately plays the role of a reverse proxy, caching replies from your application to send them back to the requesting client.

Note that the cache kernel has a special getlog () method that returns a string that can represent what happened in the cache layer.

You can debug and validate your cache policy in the development environment.

Error_log ($kernel->getlog ());

The AppCache object is a reasonable default configuration, but you can also tune it by overriding the GetOptions () method to set options.

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 ' and      false,      ' Allow_revalidate '    = False,      ' stale_while_revalidate ' = 2,      ' stale_if_error ' and '     = 60,    );  }}

Note that here no matter how to rewrite the GetOptions () method, where the debug option is automatically set by the debug value of the wrapped Appkernel.

Here are some important optional options:

Default_ttl: When no explicit refresh information is provided in the reply, a buffered entity should be considered a fresh time in seconds. An explicit setting of Cache-control or Expires header overrides this parameter value. The default value is 0.
Private_headers: The request header group, which triggers the "private" cache-control behavior on the reply, whether the reply is explicitly declared public or private through the Cache-control directive. The default is authorization and cookies.
Allow_reload: Specifies whether the client is allowed to force the cache to reload by specifying the Cache-control "no-cache" directive in the request. Sets it to true when the RFC2616 specification is met. The default value is False.
Allow_revalidate: Specifies whether the client is allowed to force the cache to be re-checked by specifying the "max-age=0" Directive of Cache-control in the request. Sets it to true when the RFC2616 specification is met. The default value is False.
Stale_while_revalidate: Used to specify a default number of seconds (the interval is seconds because the reply TTL accuracy is 1 seconds), and a stale reply can be returned immediately when the cache is also re-checked in the background (default is 2) This setting is overridden by the stale-while-revalidate HTTP cache-control extension (RFC 5861).
Stale_if_error: Specifies 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 is overridden by the Stale-if-error HTTP cache-contorl extension (RFC5861)

If debug is set to True,symfony2 it will automatically add a X-symfony-cache header to the reply to save information about the cache clicks and missing.

Conversions from one reverse proxy to another:

SYMFONY2 reverse Proxy is a very useful tool for developing your site or deploying your site to a shared host and you cannot 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. That's why we recommend using varnish or squid to your operating server. The good news is that it's easy to change from one proxy server to another, simply without you having to modify any program code. You can start by using Symfony2 's reverse proxy until the blocking increases when you upgrade to varnish.

Note: Symfony2 reverse proxy execution efficiency 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:

In order to take advantage of the available cache layer, your application must be able to communicate which of its replies can be cached and when/how the cache will become stale rules. These are implemented by setting the HTTP cache header on the reply (response).

Remember, "HTTP" is simply a simple text language that communicates between a Web client and a server. When we say HTTP caching, we say that it allows the client and the server to exchange information about the cache.

HTTP Specifies 4 response cache headers, which we need to look at:

Cache-control
Expires
ETag
Last-modified

One of the most important is the Cache-control head, which is actually a collection of various cache information.

Cache-control Header

The Cache-control header is the only one whose interior contains a wide variety of information about whether a response can be cached. Each piece of information is separated by commas.

Cache-control:private,max-age=0,must-revalidatecache-control:max-age=3600,must-revalidate

Symfony provides an abstraction of the Cache-control head, making it more controllable.

$response = new response ();//Mark response as Public or private$response->setpublic (); $response->setprivate ();// Set the maximum age for private or shared age$response->setmaxage (600); $response->setsharedmaxage (+/); 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 was mistakenly stored in the shared cache, it might later be returned to countless unused users. Imagine if your account information is cached and then returned to every user who subsequently requests their own account page. To handle this situation, each reply may be set to public or private.

The public description gives a reply that may be saved by private and shared caches.
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 cautiously defaults each reply to private. To use the benefits of a shared cache (such as a Symfony2 reverse proxy), the reply must be explicitly set to public.

Security methods:

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

When your application replies to a GET or head request, you will never change the state of your application. Even if you do not use the gateway cache, the presence of the proxy cache means that any get and head requests may or may not actually reach your server.

Do not expect the Put,post or delete method to be cached. These methods are used to mean changes in the state of your application. Caching them will block some kind of request to access or change your application.

Cache rules and default settings

HTTP 1.1 By default allows caching of anything unless there is an explicit Cache-control header. In practice, most caches do not perform any cache activity when a request has a cookie, an authorization header, a non-secure method (such as Put,post,delete), or when a request has a redirect code.

When the developer does not make any settings, Symfony2 will automatically set a reasonably 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 there is another cache header present), its value is set to Private,must-revalidate;

If at least one Cache-control instruction is set and no ' public ' or ' private ' instructions are explicitly added, Symfony2 will automatically add a private directive (except where s-maxage is set).

HTTP Expiration and checksum

The HTTP specification defines two cache models:
Expiration model, you only need to specify how long a response should be considered "fresh" by including a cache-control and/or a expires header. Cache understanding expiration will no longer cause the same request to reply until the cached version reaches its expiration time to become "stale" stale.

The calibration model is often needed when the page is truly dynamic (their presentation often changes). This model, the cache stores response, but requires the service to validate that each request is cached response still.

The application uses a unique response identifier (ETAG header) and/or timestamp (last-modified header) to check whether the page has changed since it was cached.

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

Expired:

The expiration model is a more efficient and straightforward model in both models, and it should be possible to be used at all times. When a response is cached using an expiration method, the cache stores the response and returns it directly to the request without accessing the application until it expires.

The expiration model can be expertly used by one or two, almost identical, 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 the response is considered stale after this date or time. The Expires header can be set by the response SetExpires () method. It requires a DateTime instance as an input parameter.

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

The resulting HTTP header results in the following:

Expires:thu, Mar 16:00:00 GMT

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

We note that the source service does not need to send a date header before the HTTP Specification version 1.1. Therefore, a cache (such as a browser) may need to rely on its local always to evaluate the expires header, resulting in a clock skew during the computing life cycle. Another limitation of the Expires header is the specification: "The http/1.1 service should not send the expires date for more than one year in the future." "

Expiration and Cache-control Header

Because of the limitations of the expires head, most of the time, you should use the Cache-control head to replace it. Recall that the Cache-control header is used to specify multiple different cache directives. For expiration, there are two instructions, max-age and s-maxage. The first one is used by all caches, but the second one is only used to share the cache.

Set a number of seconds, after this number of seconds response is considered obsolete. $response->setmaxage (600);//Ibid., but only for shared caches. $response->setsharedmaxage (600); The Cache-control header will use the following format (it may have other directives): cache-control:max-age=600, s-maxage=600

Check:

When the underlying data changes to require immediate updating of the cache resources, the expiration model becomes inadequate. Under the expiration model, the application is not required to return the updated response until the last expiration of the cache becomes stale content.

The calibration model solves this problem. Under the checksum model, the cache is persisted response. The difference is that for each request, the cache asks whether the response of the application cache 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 the cached response for the requesting user.

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

304 Status code means no modification. It's important because it doesn't contain an entire requested content, but just a lightweight guide set that tells the cache that it should use the version it saves now to reply to the request. Similar to expiration, there are also two different HTTP headers that can be used to implement a checksum model: ETag and last-modifed

Checksum ETag Header

The ETag header is a string (also called a "Entity-tag") that is the unique identifier of a performance of the target resource. It is completely generated and set up 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 the equivalent of two different versions of a resource.
Like fingerprints, each etag must be unique in all representations of the same resource. Let's simply implement a build etag using MD5 encrypted reply content 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 the request with the ETag on the Response. If two matches, the method automatically sets the response status code to 304.

This algorithm is very simple and very general, but you need to create a complete response before you can compute the etag, and the calibration model is a suboptimal choice. In other words, it saves bandwidth and the single does not save CPU utilization.

Symfony2 also supports weak etag by passing true as a second parameter to the Setetag () method.

Checksum last-modified Header

The last-modified header is the second form of the calibration model. According to the HTTP specification, the "Last-modified header field specifies the date and time, at which time the source server believes that the performance is the last modified version." “
In other words, the application decides whether the cached content should be updated if it is updated based on the cache content being cached. For example, you can use the latest update date for all objects that need to be evaluated for resource performance as Last-modified header values:

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 last-modified header in the request to the If-modified-since header and Response. If they are equal, response will be set to a 304 status code.

Note that the if-modified-since request header is equal to the last-modified header that is ultimately sent to the client-specific resource. This is how the client and the server communicate with each other to determine whether the resource has been updated since it was cached.

Use validation to optimize your code:

The primary purpose of any caching strategy is to mitigate application loading. In other words, the less your application does to return to 304 response, the better. The Response::isnotmodified () method is done by exposing a simple and efficient 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 of storage instances.  $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 for the given request response not modified  if ($response->isnotmodified ($this->getrequest ())) {    //return 304 immediately Response    return $response;  } else{    //Do some more work-for example get more data    $comment =//    ... or render a template return with the $response you have opened    $this->render (' MyBundle:MyController:article.html.twig ',        Array (' Article ' = $article, ' comments ' = $comments),        $response    );  }

When response is not modified, isnotmodified () automatically sets the response status code to 304, removes the response content, and removes some headers that do not need to be 304.

Different reply responses:

So far, we have assumed that each URI has only one representation of the target resource. By default, the HTTP cache is executed by using the URI resource as the cache key. If two people request a URI for the same cacheable resource, the second user gets 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 a client supports you in compressing a page, there are two representations of any given URI: one is when the client supports compression, and one is an unsupported representation. This time the accept-encoding value of the request header determines which to use.

In this case, we need to reply to a specific URI cache for a compressed version and a non-compressed version that returns them based on the requested accept-encoding value. This is done by vary response header, vary is a different header separated by commas, and its value triggers a different representation of the requested resource.

Vary:accept-encoding,user-agent

Note that this particular vary header will cache the different versions of each resource based on the URI and the accept-encoding and User-agent request headers.

The response object provides a clean interface to manage the vary header:

Set a vary header $response->setvary (' accept-encoding ');//Set multiple vary headers $response->setvary (' accept-encoding ', ' User-agent '));

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

Expiration and checksum:

You can of course use both the checksum expiration in the same response. Because the expiration is better than the checksum, you can easily choose from two of them according to the benefits. In other words, by using both expiration and checksum, you can instruct the cache to serve the cached content while the background interval checks to see if the content is still valid.

More Response methods:

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

Flag response outdated $response->expire ();//forcing response to return a response$response->setnotmodified () that is suitable for 304 without content;

In addition, the HTTP headers that are most relevant to the cache can be set by a separate method, Setcache ().

Set the cache parameters via a call to the $response->setcache (array (  ' etag '     = = $etag,  ' last_modified ' = = $date,  ' max _age '    = ', '  s_maxage '   =,  ' public '    = True,  //' private '  = true,);

Using ESI (Edge Side includes)

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

Fortunately, Symfony2 provides a solution for these situations, based on ESI technology. It allows the page to specify a different cache policy than the master.

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

      Some    
 
      
 content
  more    content  

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

When the request is processed, the gateway caches the entire page from its cache or from the application behind it requesting a reply. In other words, the gateway cache fetches both the included page fragment from the cache and the page fragment that replies to the request again from the application behind it. When all ESI tags are parsed, the gateway caches merge each ESI content to a home page and return the final content to the client. All of this happens transparently at the gateway cache level (outside of your program). You will see that if you choose ESI tags, Symfony2 makes this process of containing them almost effortless.

Using ESI in Symfony2

First, the use of ESI requires confirmation that it is already open 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 ticker at the bottom of the content. With ESI, we can cache the news ticker independent of the rest of the page.

Public Function indexaction () {  $response = $this->render (' MyBundle:MyController:index.html.twig ');  $response->setsharedmaxage (+);  return $response;}

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

Twig format:

{% Render ' ...: News ' with {}, {' Standalone ': true}%}

PHP Format:

<?php echo $view [' Actions ']->render (' ...: News ', Array (), Array (' standalone ' = true)?>

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

You may wonder why you should use a helper method instead of writing ESI tags directly. This is because using helper allows your application to work even without the gateway cache being installed. Let's take a look at how it works.

When standalone is False (also the default), Symfony2 merges the contained page content to a home page before sending response to the client.

However, when standalone is true, and if Symfony2 discovers that it has a dialog with the 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 will only merge the contents of the contained label page into a primary as it did when standalone is false.

The 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 for only 60 seconds.

One prerequisite for ESI is that the embedded action can be accessed through a URL so that the gateway cache can get it independently of the rest of the page. Of course, an action cannot be accessed through a URL unless there is a route pointing to it. The SYMFONY2 is responsible for this through a generic routing and controller.

In order for ESI to contain the label to work properly, you must define the _internal route:

YAML format:

# app/config/routing.yml_internal:  resource: "@FrameworkBundle/resources/config/routing/internal.xml"  Prefix:  /_internal

XML format:

 
  <?xml version= "1.0" encoding= "UTF-8"?>
 
    
  
   
 
  

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 the route allows all actions to be accessed through a URL, you can protect it by using the Symfony2 Firewall (which allows access to your reverse proxy's IP range) content.

One of the big advantages of a caching strategy is that you can make your application as dynamic as possible while minimizing touch to the application.

Once you start using ESI, remember to use the S-maxage directive instead of max-age. Because the browser accepts only aggregated resources, it does not 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.

The two outer two useful options supported by render helper:
ALT: Used as the alt attribute of the ESI tag, which allows you to specify an alternate URL when src cannot be found.
Ignore_errors: If set to true, a onerror property is added to ESI, and the property value is set to continue, and in a failed event, the gateway cache will only silently remove the ESI label.

Cache invalidation:

"There are two big problems in computer science: Cache invalidation and naming things,"---Phil karlton

You never need to fail the cache data because the failure has already been taken into account in the HTTP cache model. If you use checksums, you never need to verify anything by definition, and if you use expiration and expire a resource, 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 concerned about failure, you can switch between reverse proxies without changing any application code.

In fact, all the reverse proxies provide a way to erase the 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 the HTTP method of the request as purge.

Here is how to configure the Symfony2 reverse proxy support 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 (' purged ');    }    return $response;  }}

Note that you must protect your purge HTTP method to avoid using some method to clear your cached data.

Summarize:

Symfony2 is designed to follow a proven road rule: HTTP. The cache is no exception. Mastering the Symfony2 cache system means being familiar with HTTP caching patterns and using them effectively.

This means that you cannot rely solely on Symfony2 documentation and code samples, and you must understand the wider knowledge about HTTP caching and gateway caching, such as varnish.

It is hoped that this article is helpful to the PHP program design based on Symfony framework.

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.