Reprinted from: HTTPS://WWW.JIANSHU.COM/P/32733A356ACF
Network-specific latency and the cost of data transmission, restricting the Internet to quickly obtain web resources. To this end, the HTTP protocol introduces caching to space-time, allowing the browser to cache and reuse the acquired resources, solve the problem of high network latency and data transfer costs, and improve the access experience. With the evolution of the HTTP protocol 1.0->1.1->2, there are some changes in the part about cache control. But I think that when developing Web services, the first thing to look at is the request Header if-modified-since/response header last-modified, the request Header if-none-match/response header ETag, the response header Cache-control. Because these three HTTP headers can satisfy most of your HTTP caching needs, the vast majority of browsers today support these three HTTP headers. All we have to do is make sure that each server response provides the correct HTTP header instructions to guide when the browser caches the response and how long the cache is cached. where is the HTTP cache.
As shown in Figure 1, the HTTP cache exists in the browser and Web proxy. Of course, within the server, there are various caches, such as local cache guavacache/ehcache, distributed cache Memcached/redis, etc., but this is not the HTTP cache discussed in this article. The so-called HTTP cache control, is a protocol, by setting different response header Cache-control to control the browser and Web proxy to the cache usage policy, by setting the request Header if-modified-since/response header last-modified, The request header if-none-match/the response header ETag to validate the validity of the cache.
In this paper, the request head if-modified-since/response Head last-modified, the request header if-none-match/response Head ETag, the response head Cache-control is practiced, analyzes these three kinds of HTTP cache head in the browser and the server performance. Practice, the service-side implementation using the spring Boot+java, the front-end implementation using HTML, access method in conjunction with the browser and NC command line cross-use, where NC executes the following command, on port 8080 to establish a connection, you can set the request header, Analog browser send input HTTP request.
NC 127.0.0.1 8080
Note: Because the front-end and back-end print time object classes are different, the GMT or CST time may be printed, GMT is 8 hours later than CST. Request Header if-modified-since/response header last-modified
As shown in Figure 2, the request Header if-modified-since/Response Header last-modified Interactive process as follows: as shown in the red section of Figure 2, when the browser first requests a resource from the server, the server returns status 200 and the resource contents, At the same time, in the response header last-modified field mark the resource content at the end of the server was modified, similar format: last-modified:wed, 10:34:50 GMT, For the next browser to use in the request header if-modified-since, as shown in the purple section of Figure 2, the second time the browser requests the resource from the server, according to the HTTP protocol, The browser writes the response header Last-modified value returned by the last server on the request header if-modified-since, asking the server if the resource has been modified after that time, formatted like this: if-modified-since:wed, 2017 10:34:50 GMT; As shown in the green section of Figure 2, when the server resource file has been modified, re-returns the resource and status code 200 to the browser, while in the response header the Last-modified field marks the last modified time of the resource content in the server, as shown in the blue section of Figure 2, When the server resource content has not been modified, only return the status Code 304 (not Modified) to the browser, do not return the request resource, the browser uses the local cache according to 304, thus saving bandwidth and improving the response speed of the Web page.
The following examples are practiced.
The backend Java code is as follows, where the Cachecontrolcontroller#getresourcelastmodified () method marks the last modification time of the resource and is used to set last-modified:wed, 2017 19:30:20 GMT.
Package com.demo.web.http;
Import org.springframework.web.bind.annotation.RequestMapping;
Import Org.springframework.web.context.request.ServletWebRequest;
Import Java.time.LocalDateTime;
Import Java.time.ZoneId;
Import Java.time.ZonedDateTime;
@RequestMapping ("http") public
class Cachecontrolcontroller {
@RequestMapping ("/cache-control/ Last-modified ") Public
String lastmodified (servletwebrequest request) {
if (request.checknotmodified ( Getresourcelastmodified ())) {
//it'll return 304 with empty body
return null;
}
return "http/cache-control/last-modified";
}
private static Long getresourcelastmodified () {
Zoneddatetime ZDT = Zoneddatetime.of (Localdatetime.of (2017, 8, 2,< C17/>19, (),
zoneid.of ("GMT"));
Return Zdt.toinstant (). Toepochmilli ();
}
}
Front-end HTML code:
<! DOCTYPE html>
As shown in the green box in Figure 3, when the request header if-modified-since:wed, 19:30:15 GMT is earlier than the resource last modified time Wed, 19:30:20 GMT, indicates that the Web resource has been modified since the last return, So the server returns the resource content, returns the status code 200, and returns the resource last modified time in response header last-modified:wed, 19:30:20 GMT. As shown in the red and green boxes in Figure 4, when the request header if-modified-since:wed, 19:30:15 GMT equals or later than the resource last modified time Wed, 19:30:20 GMT, indicating that the resource was not has been modified, so the server only returns status code 304, does not return the resource content, the browser uses the local cache resource.
Request Header if-none-match/Response header ETag
The ETag is the full entity Tag, which identifies a web resource that reflects changes in resource content. In a specific implementation, the ETag can be a hash value for a Web resource, or it can be a version number maintained internally by a server.
As shown in Figure 5, the request Header if-none-match/Response Header ETag interaction process is as follows: as shown in the red section of Figure 5, the first time the browser requests a resource from the server, the server returns the status code 200 and the resource content, while the response header ETag field identifies the resource content in the format similar to: ETag: "50b1a1d4f885c61:df4" for the next browser to use in the request header If-none-match, as shown in the purple section of Figure 5, the second time the browser requests the resource from the server, according to the HTTP protocol, browser in the request header If-none-match write to the last server returned the response header ETag value, and the server's resource identification compared to determine whether the resource has been modified, similar format: if-none-match: "50B1A1D4F885C61:DF4"; As shown in the green section of Figure 5, when the server resource content has been modified, the browser returns the resource and status code 200, while the response header ETag field marks the entity value of the resource file, as shown in the blue section of Figure 5, when the server resource content has not been modified, only give the browser return status code 304 (not Modified), does not return the request resource, the browser uses the local cache according to 304, saves the bandwidth, improves the webpage access speed.
The following examples are practiced.
The backend Java code is as follows, the Cachecontrolcontroller#getetag () method indicates that the resource uniquely identifies the token and sets the ETag value to: "Etag_version".
Package com.demo.web.http;
Import org.springframework.web.bind.annotation.RequestMapping;
Import Org.springframework.web.context.request.ServletWebRequest;
@RequestMapping ("http") public
class Cachecontrolcontroller {
@RequestMapping ("/cache-control/etag")
Public String ETag (servletwebrequest request) {
if (request.checknotmodified (Getetag ())) {
//it would return 304 With empty body
return null;
}
return "Http/cache-control/etag";
}
private static String Getetag () {
return ' etag_version ';
}
}
Front-end HTML code:
<! DOCTYPE html>
As shown in Figure 6, when the server resource uniquely identifies token: "Etag_version" is not equal to If-none-match: "Etag_version_new", indicating that the resource has changed since the last return, so the server returns the resource content and status code 200 again.
Figure 6 Server Resource Updated (ETAG)
As shown in Figure 7, when the server resource uniquely identifies token: "Etag_version" equals If-none-match: "Etag_version", indicating that the resource has not changed since the last return, so the server does not return the resource file, only the status code 304 is returned, The browser uses a local cache resource.
Request Header if-modified-since/response header last-modified, request header if-none-match/Response Header ETag Summary
How do last-modified and etags help improve performance?
The server first generates the LAST-MODIFIED/ETAG tag and returns the HTTP response header to the client, which is later used by the server to determine if the page has been modified. The client passes the Last-modified/etag token back to the server through the request header If-modified-since/if-none-match, requiring the server to validate its (client) cache.
The process is as follows:
1. The client requests a page (a).
2. The server returns page A, and a plus the response header Last-modified/etag.
3. The client presents the page and caches the page along with Last-modified/etag.
4. The Customer requests page A again and passes the Last-modified/etag returned by the server on the last request as the request header If-modified-since/if-none-match to the server.
5. The server checks the If-modified-since/if-none-match and determines that the page has not been modified since the last client request, directly returning the status code 304 and an empty response body. Cache-control
Each Web resource can define its own cache policy through the HTTP response header Cache-control, Cache-control control who can cache the response under what conditions and how long it can be cached. The quickest request is that you do not have to communicate with the server: with a local copy of the response, we can avoid all network delays and the cost of data transfer. To do this, the HTTP specification allows the server to return a series of different cache-control instructions, controlling how long the browser or other relay proxy cache caches a response and how much time it caches.
The Cache-control response header is defined in the http/1.1 specification, and all current browsers support Cache-control, replacing the headers previously used to define the response cache policy (for example, Expires).
Cache-control commonly used directives include the following four, the following will be an example of the four instructions to practice. Max-age No-cache No-store public/private
Max-age
The max-age directive specifies the maximum amount of time (in seconds) to allow the retrieved response to be reused, starting with the current request. For example, cache-control:max-age=30 indicates that the response can be cached and reused for 30 seconds. Note that the browser does not send any requests to the server within the time specified by Max-age, including verifying that the cache is valid, that is, if the resources on the server have changed during that time, the browser will not be notified and the old version of the resource is used. So when setting the length of the cache time, you need to be cautious.
The backend Java code is as follows, the response header setting: Cache-control:max-age=30.
Package com.demo.web.http;
Import Org.springframework.http.CacheControl;
Import org.springframework.web.bind.annotation.RequestMapping;
Import Javax.servlet.http.HttpServletResponse;
Import java.util.Date;
Import Java.util.concurrent.TimeUnit;
@RequestMapping ("http") public
class Cachecontrolcontroller {
@RequestMapping ("/cache-control/max-age") Public
String MaxAge (httpservletresponse response) {
System.out.println ("Server access Time:" + new Date ());
String Headervalue = Cachecontrol.maxage (timeunit.seconds). GetHeaderValue ();
Response.AddHeader ("Cache-control", headervalue);
return "Http/cache-control/max-age";
}
}
Front-end HTML code:
<! DOCTYPE html>
As shown in Figure 8, the first time the browser requests http://127.0.0.1:8080/http/cache-control/max-age, the server returns the response header:
Cache-control:max-age=30
date:wed, 13:09:46 GMT
Browser Render page access time: Wed 21:09:46 gmt+0800 (CST).
Server-side Print log: Server access time: Wed 21:09:46 CST 2017. Figure 8 first time access to Max-age
As shown in Figure 9, the browser second request Http://127.0.0.1:8080/http/cache-control/max-age, the response header and Figure 8, the same is the page access time: Wed 21:10:03 gmt+ 0800 (CST), Status code is more (from disk cache), and the server does not have a print log, these differences indicate that the second request within 30s does not communicate with the servers, the browser directly uses the local cached copy to render the page. Figure 9 Second visit to Max-age
the difference between the from cache and the 304 not Modified
The " from cache" is the browser does not confirm with the server, directly using the browser local cache, while 304 not Modified is the browser and server to confirm the cache validity, and then use the browser cache. (from cache) is the fastest because you do not need to access the remote server and use the local cache directly. The process of 304 is to request the server first, and then the server tells the browser that the resource has not changed and the browser uses the local cache.
As shown in Figure 10, when the Http://127.0.0.1:8080/http/cache-control/max-age is re-requested after 30s (MAX-AGE=30), the server returns the response header:
Cache-control:max-age=30
date:wed, 13:10:31 GMT
Browser Render page access time: Wed 21:10:32 gmt+0800 (CST). Server-side Print log: Server access time: Wed 21:10:31 CST 2017. Compared with Figure 8 and Figure 9, the browser no longer uses the locally cached copy render page after 30s, requesting server resources again. Figure 10 Third visit to Max-age
max-age=0
The
Max-age=0 is a special case that indicates that the response can be re-cached and reused for 0 seconds, max-age instructions, and then gives a conclusion. The
Backend Java code is as follows, the response header setting: Cache-control:max-age=0.
package com.demo.web.http;
Import Org.springframework.http.CacheControl;
Import org.springframework.web.bind.annotation.RequestMapping;
Import Org.springframework.web.context.request.ServletWebRequest;
Import Javax.servlet.http.HttpServletResponse;
Import Java.util.Date;
Import Java.util.concurrent.TimeUnit; @RequestMapping ("http") public class Cachecontrolcontroller {@RequestMapping ("/cache-control/max-age0") public St Ring MAXAGE0 (servletwebrequest request, httpservletresponse response) {System.out.println ("Server access Time:" + New Date ()
);
if (Request.checknotmodified (Getetag ())) {//it'll return 304 with empty body return null;
} String headervalue = Cachecontrol.maxage (0, Timeunit.seconds). GetHeaderValue ();
Response.AddHeader ("Cache-control", Headervalue);
return "HTTP/CACHE-CONTROL/MAX-AGE0";
} private static String Getetag () {return ' etag_version '; }
}
Front-end HTML code:
<! DOCTYPE html>
As shown in Figure 11, the first time the browser requests HTTP://127.0.0.1:8080/HTTP/CACHE-CONTROL/MAX-AGE0, the server returns the response header:
Cache-control:max-age=0
Date:thu 12:45:51 GMT
Browser rendered page access time: Thu 20:45:52 gmt+0800 (CST). Server-side Print log: Server access time: Thu 20:45:51 CST 2017. Figure 11 first access max-age0 as shown in Figure 12, the second time the browser requests HTTP://127.0.0.1:8080/HTTP/CACHE-CONTROL/MAX-AGE0, the server returns to status
Code 304 (not Modified), response header:
Cache-control:max-age=0
Date:thu 12:46:09 GMT
Browser rendered page access time: Thu 12:46:09 gmt+0800 (CST). Server-side Print log: Server access time: Thu 20:46:09 CST 2017.
Indicates that in the case of max-age=0, the response is cached and reused for 0 seconds, and the browser requests the server for resources each time. Figure 12 Second visit to MAX-AGE0
Max-age Conclusion
Max-age>0, the response caches and reuses the specified number of seconds and uses the browser cache copy directly within the specified number of seconds.
Max-age<=0, an HTTP request acknowledgement is sent to the server to see if the resource has been modified. 200 and up-to-date resources are returned with modifications, and 304 is returned without modification, using a copy of the browser cache.
No-cache
If the server is setting Cache-control:no-cache in the response header, the browser must first confirm with the server whether the last resource returned was changed before using the cached resource, and if the resource has not been changed, use the cached copy of the browser directly to avoid re-downloading. Whether the response before this verification is modified is implemented by the request header If-none-match and the response header ETag described above. Note that the name No-cache is a bit misleading. After setting No-cache, it is not that the browser will not cache the data, but when the browser is using cached data, it is necessary to confirm that the resource is consistent with the server. If No-cache is set, and the ETag implementation does not reflect changes in the resource, the browser's cache data is not updated, and the browser and the server each request connection degrades performance. Therefore, when the server resources are not changing frequently, setting No-cache has decreased performance.
The backend Java code is as follows, the response header setting: Cache-control:no-cache.
package com.demo.web.http;
Import Org.springframework.http.CacheControl;
Import org.springframework.web.bind.annotation.RequestMapping;
Import Org.springframework.web.context.request.ServletWebRequest;
Import Javax.servlet.http.HttpServletResponse;
Import Java.util.Date; @RequestMapping ("http") public class Cachecontrolcontroller {@RequestMapping ("/cache-control/no-cache") public St Ring NoCache (servletwebrequest request, httpservletresponse response) {System.out.println ("Server access Time:" + New Date (
));
if (Request.checknotmodified (Getetag ())) {//it'll return 304 with empty body return null;
} String Headervalue = Cachecontrol.nocache (). GetHeaderValue ();
Response.AddHeader ("Cache-control", Headervalue);
return "Http/cache-control/no-cache"; } private static String Getetag () {return