首页 > 代码库 > HTTP缓存机制[译文]

HTTP缓存机制[译文]

本文翻译自: https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching ,主要用于个人记录和共享,若有疏漏错误,请不吝指正,谢谢!

 

The performance of web sites and applications can be significantly improved by reusing previously fetched resources. Web caches reduce latency and network traffic and thus lessen the time needed to display a representation of a resource. By making use of HTTP caching, Web sites become more responsive.

通过重用已获取的资源,可大幅提高web站点和应用的性能。由于web缓存减少了延迟和网络流量,因此缩短了展示一个资源所需的时间。通过使用HTTP缓存机制,web站点可实现更快更灵活的响应。

Different kinds of caches 不同类型的缓存

Caching is a technique that stores a copy of a given resource and serves it back when requested. When a web cache has a requested resource in its store, it intercepts the request and returns its copy instead of re-downloading from the originating server. This achieves several goals: it eases the load of the server that doesn’t need to serve all clients itself, and it improves performance by being closer to the client, i.e., it takes less time to transmit the resource back. For a web site, it is a major component in achieving high performance. On the other side, it has to be configured properly as not all resources stay identical forever: it is important to cache a resource only until it changes, not longer.

缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。当发起一个请求时,web缓存会判断是否已有此请求的一个副本(之前已经请求过一次并且被缓存了),若有,则缓存会拦截此请求,并直接返回缓存中的请求结果副本,从而防止重新到源服务器下载资源。缓存的目的:减轻服务器压力(服务器不用每次为所有客户端提供服务了),提高访问效率(因为缓存离客户端最近,可直接提供资源副本,也可节省很多传输时间)。对于网站来讲,缓存是建设高性能网站的最重要的组件,但在另外方面,缓存必须进行合理的配置才能达到最佳效果,因为并非所有资源都是永久不变动的,所以我们需要保证某个资源的缓存仅在它未变动时有效。

There several kinds of caches: these can be grouped into two main categories: private or shared caches. A shared cache is a cache that stores responses for reuse by more than one user. A private cache is dedicated to a single user. This page will mostly talk about browser and proxy caches, but there are also gateway caches, CDN, reverse proxy caches and load balancers that are deployed on web servers for better reliability, performance and scaling of web sites and web applications.

所有不同类型的缓存,大致可以归为两类:私有缓存 和 共享缓存。共享缓存中存储的资源副本是供所有用户使用的(比如不同浏览器,不同机器),而私有缓存是仅提供给单个用户的专有缓存(不同用户保留不同私有缓存副本)。本文仅讨论浏览器缓存和代理缓存,但就目前来讲,还有很多其他类型的缓存,比如:网关缓存、CDN、反向代理缓存、负载均衡(负载均衡是部署在服务器端的,为多个web服务器提供更可靠、更高性能以及更易进行规模化扩展的方案)。

技术分享

Private browser caches 浏览器(私有)缓存

A private cache is dedicated to a single user. You might have seen "caching" in your browser‘s settings already. A browser cache holds all documents downloaded via HTTP by the user. This cache is used to make visited documents available for back/forward navigation, saving, viewing-as-source, etc. without requiring an additional trip to the server. It likewise improves offline browsing of cached content.

私有缓存是单个用户的专有缓存,一般来讲,在你的浏览器设置中就可以看到“缓存”的选项。浏览器缓存保留了用户通过HTTP下载的所有文档资源,前进/后退、保存、查看源代码等操作都可以使用到此缓存,而不用再重新访问服务器。同样的,有了缓存,我们还可以实现脱机浏览文档和资源。

Shared proxy caches 代理(共享)缓存

A shared cache is a cache that stores responses to be reused by more than one user. For example, an ISP or your company might have set up a web proxy as part of its local network infrastructure to serve many users so that popular resources are reused a number of times, reducing network traffic and latency.

共享缓存中存放的访问结果是提供给多个用户使用的。比如:ISP或你的公司可能会组建一个本地网络的代理,该代理(服务器)会缓存不同用户访问外网时请求的公共资源,这些公共资源被缓存后,下次其他用户也访问同一资源时,就会重用此已被缓存的资源(就不用再向源站获取了),从而减少了网络浏览和延迟。

Targets of caching operations 缓存操作的目标

HTTP caching is optional, but reusing a cached resource is usually desirable. However, common HTTP caches are typically limited to caching responses to GET and may decline other methods. The primary cache key consists of the request method and target URI (oftentimes only the URI is used as only GET requests are caching targets). Common forms of caching entries are:

HTTP缓存虽然是可选的,但一般是所有人都需要的。HTTP缓存通常只缓存GET请求(其他请求一般不缓存),缓存的主键由请求方法和目标URI(通常只用到URI,因为一般仅缓存GET请求)组成。通常的缓存条目有:

  • Successful results of a retrieval request: a 200 (OK) response to a GET request containing a resource like HTML documents, images or files.
  • 成功的查询请求的结果数据:状态码为200的GET响应(结果中可能包含资源数据如:HTML文档、图片或文件等)
  • Permanent redirects: a 301 (Moved Permanently) response.
  • 永久性跳转:状态码为301(Moved Permanently)的响应
  • Error responses: a 404 (Not Found) result page.
  • 返回出错,文档不存在:状态码为404(Not Found)的响应
  • Incomplete results: a 206 (Partial Content) response.
  • 不完整的结果数据:状态码为206(Partial Content)的响应(通过Range头发起的请求所返回的结果,Range用于只获取文档某一部分)
  • Responses other than GET if something suitable for use as a cache key is defined.
  • 其他非GET请求的结果(如果这些结果比较适合作为缓存的话)

A cache entry might also consist of multiple stored responses differentiated by a secondary key, if the request is target of content negotiation. For more details see the information about the Vary headerbelow.

Controlling caching

The Cache-control header

The Cache-Control HTTP/1.1 general-header field is used to specify directives for caching mechanisms in both requests and responses. Use this header to define your caching policies with the variety of directives it provides.

No cache storage at all

The cache should not store anything about the client request or server response. A request is sent to the server and a full response is downloaded each and every time.

Cache-Control: no-storeCache-Control: no-cache, no-store, must-revalidate

No caching

A cache will send the request to the origin server for validation before releasing a cached copy.

Cache-Control: no-cache

Private and public caches

The "public" directive indicates that the response may be cached by any cache. This can be useful, if pages with HTTP authentication or response status codes that aren‘t normally cacheable, should now be cached. On the other hand, "private" indicates that the response is intended for a single user only and must not be stored by a shared cache. A private browser cache may store the response in this case.

Cache-Control: privateCache-Control: public

Expiration

The most important directive here is "max-age=<seconds>" which the maximum amount of time a resource will be considered fresh. Contrary to Expires, this directive is relative to the time of the request. For the files in the application that will not change, you can usually add aggressive caching. This includes static files such as images, CSS files and JavaScript files, for example.

For more details, see also the Freshness section below.

Cache-Control: max-age=31536000

Validation

When using the "must-revalidate" directive, the cache must verify the status of the stale resources before using it and expired ones should not be used. For more details, see the Validation section below.

Cache-Control: must-revalidate

The Pragma header

Pragma is a HTTP/1.0 header, is not specified for HTTP responses and is therefore not a reliable replacement for the general HTTP/1.1 Cache-Control header, although it does behave the same asCache-Control: no-cache, if the Cache-Control header field is omitted in a request. Use Pragma only for backwards compatibility with HTTP/1.0 clients.

Freshness

Once a resource is stored in a cache, it could theoretically be served by the cache forever. Caches have finite storage so items are periodically removed from storage. This process is called cache eviction. On the other side, some resources may change on the server so the cache should be updated. As HTTP is a client-server protocol, servers can‘t contact caches and clients when a resource change; they have to communicate an expiration time for the resource. Before this expiration time, the resource is fresh; after its expiration time, the resource if stale. Eviction algorithms often privileges fresh resources over stale resources. Note that a stale resource is not evicted or ignored; when the cache receives a request for a stale resource, it forwards this requests with a If-None-Match to check if it isn‘t in fact still fresh. If so, the server returns a 304 (Not Modified) header without sending the body of the requested resource, saving some bandwidth.

Here is an example of this process with a shared cache proxy:

技术分享

The freshness lifetime is calculated based on several headers. If a "Cache-control: max-age=N" header is specified, then the freshness lifetime is equal to N. If this header is not present, which is very often the case, it is checked if an Expires header is present. If an Expires header exists, then its value minus the value of the Date header determines the freshness lifetime. Finally, if neither header is present, look for a Last-Modified header. If this header is present, then the cache‘s freshness lifetime is equal to the value of the Date header minus the value of the Last-modified header divided by 10.
The expiration time is computed as follows:

expirationTime = responseTime + freshnessLifetime - currentAge

where responseTime is the time at which the response was received according to the browser.

Revved resources

The more we use cached resources, the better the responsiveness and the performance of a Web site will be. To optimize this, good practices recommend to set expiration times as far in the future as possible. This is possible on resources that are regularly updated, or often, but is problematic for resources that are rarely and infrequently updated. They are the resources that would benefit the most from caching resources, yet this make them very difficult to update. This is typical of the technical resources included and linked from each Web pages: JavaScript and CSS files change infrequently, but when they change you want them to be updated quickly.

Web developers invented a technique that Steve Sounders called revving[1]. Infrequently updated files are named in specific way: in their URL, usually in the filename, a revision (or version) number is added. That way each new revision of this resource is considered as a resource on its own that never changes and that can have an expiration time very far in the future, usually one year or even more. In order to have the new versions, all the links to them must be changed, that is the drawback of this method: additional complexity that is usually taken care by the tool chain used by Web developers. When the infrequently variable resources change they induce an additional change to often variable resources. When these are read, the new versions of the others are also read.

This technique has an additional benefit: updating two cached resources at the same time will not lead to the situation where the out-dated version of one resource is used in combination with the new version of the other one. This is very important when web sites have CSS stylesheets or JS scripts that have mutual dependencies, i.e., they depend on each other because they refer to the same HTML elements.

技术分享

The revision version added to revved resources doesn‘t need to be a classical revision string like 1.1.3, or even a monotonously growing suite of number. It can be anything that prevent collisions, like a hash or a date.

Cache validation

Revalidation is triggered when the user presses the reload button. It is also triggered under normal browsing if the cached response includes the "Cache-control: must-revalidate" header. Another factor is the cache validation preferences in the Advanced->Cache preferences panel. There is an option to force a validation each time a document is loaded.

When a cached documents expiration time has been reached, it is either validated or fetched again. Validation can only occur if the server provided either a strong validator or a weak validator.

ETags

The ETag response header is an opaque-to-the-useragent value that can be used as a strong validator. That means that a HTTP user-agent, such as the browser, does not know what this string represents and can‘t predict what its value would be. If the ETag header was part of response for a resource, the client can issue an If-None-Match in the header of future requests – in order to validate the cached resource.

The Last-Modified response header can be used as a weak validator. It is considered weak because it only has 1-second resolution. If the Last-Modified header is present in a response, then the client can issue an If-Modified-Since request header to validate the cached document.

When a validation request is made, the server can either ignore the validation request and response with a normal 200 OK, or it can return 304 Not Modified (with an empty body) to instruct the browser to use its cached copy. The latter response can also include headers that update the expiration time of the cached document.

Varying responses

The Vary HTTP response header determines how to match future request headers to decide whether a cached response can be used rather than requesting a fresh one from the origin server.

When a cache receives a request that can be satisfied by a cached response that has a Vary header field, it must not use that cached response unless all header fields as nominated by the Vary header match in both the original (cached) request and the new request.

技术分享

This can be useful for serving content dynamically, for example. When using the Vary: User-Agentheader, caching servers should consider the user agent when deciding whether to serve the page from cache. If you are serving different content to mobile users, it can help you to avoid that a cache may mistakenly serve a desktop version of your site to your mobile users. In addition, it can help Google and other search engines to discover the mobile version of a page, and might also tell them that no Cloaking is intended.

Vary: User-Agent

Because the User-Agent header value is different ("varies") for mobile and desktop clients, caches will not be used to serve mobile content mistakenly to desktop users or vice versa.

See also

  • RFC 7234: Hypertext Transfer Protocol (HTTP/1.1): Caching
  • Caching Tutorial – Mark Nottingham
  • HTTP caching – Ilya Grigorik
  • RedBot, a tool to check your cache-related HTTP headers.

HTTP缓存机制[译文]