>일반적인 문제 >완벽한 http 캐싱 전략을 설계하는 방법

완벽한 http 캐싱 전략을 설계하는 방법

angryTom
angryTom앞으로
2019-08-20 17:35:543499검색

완벽한 http 캐싱 전략을 설계하는 방법

1. 서문

프론트엔드로서는 http 캐싱을 이해하는 것이 매우 필요합니다. 인터뷰 시 꼭 필요한 부분이자, 실제 개발에 있어서 꼭 이해해야 할 필수 지식 포인트이기도 합니다. 이 글의 저자는 캐싱의 개념과 비즈니스에서 합리적인 캐싱 아키텍처를 설계하는 방법을 단계별로 설명할 것입니다. http 캐싱의 미스터리를 풀기 위한 단계입니다.

2.http 캐시 정의

클라이언트가 서버에서 리소스를 요청하면 브라우저에 "리소스의 복사본이 있는 경우 먼저 브라우저 캐시에 도착합니다. "요청하면" 이 리소스는 원본 서버가 아닌 브라우저 캐시에서 직접 가져올 수 있습니다. http 캐싱은 일반적으로 GET 요청에 대한 것이며 POST 요청은 일반적으로 캐시되지 않습니다. 왜냐하면 POST 요청에 의해 수행되는 작업은 서버의 부작용이나 비멱등성 작업이기 때문입니다. 서버 리소스가 변경되므로 요청은 자연스럽게 처리를 위한 서버입니다. 캐싱의 이점은 엄청납니다. http 요청을 줄이면 자연스럽게 서버 부담이 줄어들고 리소스 액세스 속도가 향상됩니다. 그러나 캐시를 무분별하게 사용하면 리소스 업데이트가 시기 적절하지 않게 발생하거나 리소스 업데이트가 잘못될 수도 있습니다.
http 캐싱은 강력한 캐싱과 협상된 캐싱으로 나누어지며 두 가지 캐싱 메커니즘을 하나씩 살펴보겠습니다.

3. 강력한 캐시

3.1. 강력한 캐시 정의

캐시에 적중되면 데이터가 캐시에서 직접 가져오고 요청은 서버를 통과하지 않습니다. 반환된 http 상태 코드는 200(디스크 캐시에서)

완벽한 http 캐싱 전략을 설계하는 방법

입니다. 캐시 요청 프로세스. 가상 검색의 편의를 위해 서버(실제로는 캐시 데이터가 저장되는 디스크)에 캐시 데이터베이스가 있습니다.

완벽한 http 캐싱 전략을 설계하는 방법

완벽한 http 캐싱 전략을 설계하는 방법

위의 흐름도를 잘 살펴보세요. 캐시에 적중되면 서버를 거치지 않고 직접 반환된다는 점입니다.

3.2.Http 헤더 Expires/Cache-Control은 강력한 캐시를 설정합니다

Cache-Control에는 캐시를 제어하는 ​​여러 속성이 있습니다. 강력한 캐시를 설정한다는 것은 리소스의 유효 기간을 설정한다는 의미입니다. . max-age에 대한 속성.
Express를 사용하여 시연해 보겠습니다

app.get('/script1.js', function (req, res, next) {  
  // res.header('Cache-Control', 'must-revalidate, max-age=600')    
  // res.header('Content-Type', 'text/html')
    res.header('Cache-Control', 'max-age=20')
    res.sendFile(__dirname + '/script.js')
})

완벽한 http 캐싱 전략을 설계하는 방법

Expires와 max-age는 모두 캐시주기의 수명. 차이점은 Expires는 Sun, 2027년 3월 21일 08:52:14 GMT와 같은 특정 만료 시간을 지정하는 반면, max-age는 315360000의 수명 초를 지정한다는 것입니다.

차이점은 Expires는 HTTP/1.0의 표준인 반면 max-age는 Cache-Control의 내용이며 HTTP/1.1에 정의되어 있다는 것입니다. 그러나 이후 버전과의 호환성을 위해서는 이 두 특성이 동시에 존재해야 합니다. max-age는 Expires보다 우선합니다.

4. 협상/비교 캐싱

4.1. 정의

협상 캐싱과 강제 캐싱의 차이점은 협상 캐시가 데이터를 매번 읽는다는 것입니다. 서버와 통신해야 하며 캐시 식별자가 추가됩니다. 처음으로 서버를 요청할 때 서버는 리소스를 반환하고 리소스의 캐시 식별자를 반환합니다. 이 식별자는 브라우저의 캐시 데이터베이스에 저장됩니다. 두 번째로 리소스를 요청할 때 브라우저는 먼저 캐시 식별자를 서버에 보냅니다. 서버가 식별자를 얻은 후 식별자가 일치하는지 확인합니다. 일치하지 않으면 리소스가 업데이트되었음을 ​​의미합니다. , 서버는 새 데이터와 새 캐시 식별자를 브라우저에 반환합니다. 캐시 식별자가 일치하면 리소스가 업데이트되지 않았으며 304 상태 코드가 반환되고 브라우저가 데이터를 읽습니다. 로컬 캐시 서버.

협상 캐시의 가장 큰 특징은 서버에서 검증을 거쳐야 한다는 점입니다. 협상 캐시의 검증 과정을 설명하겠습니다.

첫번째 방문:

완벽한 http 캐싱 전략을 설계하는 방법

재방문:

#🎜 🎜## 🎜🎜#

완벽한 http 캐싱 전략을 설계하는 방법 설명을 위해 흐름도를 드리겠습니다. (사진 도난, 협상 캐시도 비교 캐시가 될 수 있으며, 사진 속 비교 캐시는 협상 캐시입니다)


4.2、协商缓存如何验证

  第一次请求将response header的Last-Modified和Etag存起来,在第二次请求通过request header的If-Modified-Since和If-None-Match传到服务端进行验证,如果命中缓存,返回304,不带返回的数据,浏览器自动从缓存中获取数据资源,若未命中缓存返回200,带上数据资源。

** Last-Modified:**

服务器在响应请求时,告诉浏览器资源的最后修改时间。

완벽한 http 캐싱 전략을 설계하는 방법

** If-Modified-Since:**

再次请求服务器时,通过此字段通知服务器上次请求时,服务器返回的资源最后修改时间。

服务器收到请求后发现有头If-Modified-Since 则与被请求资源的最后修改时间进行比对。

若资源的最后修改时间大于If-Modified-Since,说明资源又被改动过,则响应整片资源内容,返回状态码200;

若资源的最后修改时间小于或等于If-Modified-Since,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache。

완벽한 http 캐싱 전략을 설계하는 방법

** Etag / If-None-Match(优先级高于Last-Modified / If-Modified-Since) **

** Etag:**

服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。

완벽한 http 캐싱 전략을 설계하는 방법

** If-None-Match:**

再次请求服务器时,通过此字段通知服务器客户段缓存数据的唯一标识。

服务器收到请求后发现有头If-None-Match 则与被请求资源的唯一标识进行比对,

不同,说明资源又被改动过,则响应整片资源内容,返回状态码200;

相同,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache。

완벽한 http 캐싱 전략을 설계하는 방법

4.3、Http头如何设置协商缓存

  在强缓存那一节说到使用Cache-Control的max-age来设置资源过期时间,那么当max-age=0的时候呢,自然浏览器第一时间发现资源过期,request header就会带着If-Modified-Since和If-None-Match去服务端验证。
所以设置response header为:

Cache-Control: max-age=0

  就可以触发协商缓存了,其实Cache-Control中还有两个属性都可以设置协商缓存 must-revalidate和no-cache
must-revalidate的意义为必须进行验证,但是它一般是和max-age一起使用的,不会单独使用,

Cache-Control: must-revalidate, max-age=600

  该头信息意义就是在资源有效期过后必须进行验证, 与只设置max-age=600的区别是,前面一个是MUST,而后面一个是SHOULD,理论上来说它们的效果是一致的。

  no-cache的意义千万不能理解为不缓存,下面两段代码的意义是一样的,即请求必须进行验证,才可以使用缓存资源,注意是MUST

Cache-Control: no-cacheCache-Control: must-revalidate, max-age=0

  如果要不缓存,每次都请求新的资源应该使用

Cache-Control: no-store

5、关于缓存的Http头总结

5.1、"no-cache", "no-store", "must-revalidate"

  Cache-Control字段可以设置的不仅仅是max-age存储时间,还有其他额外的值可以填写,甚至可以组合。主要使用的值有如下:

  no-cache: 虽然字面意义是“不要缓存”。但它实际上的机制是,仍然对资源使用缓存,但每一次在使用缓存之前必须(MUST)向服务器对缓存资源进行验证。

  no-store: 不使用任何缓存

  must-revalidate: 如果你配置了max-age信息,当缓存资源仍然新鲜(小于max-age)时使用缓存,否则需要对资源进行验证。所以must-revalidate可以和max-age组合使用Cache-Control: must-revalidate, max-age=60

  有趣的事情是,虽然no-cache意为对缓存进行验证,但是因为大家广泛的错误的把它当作no-store来使用,所以有的浏览器也就附和了这种设计。这是一个典型的劣币驱逐良币。

5.2、Expires VS. max-age

  Expires和max-age都是用于控制缓存的生命周期。不同的是Expires指定的是过期的具体时间,例如Sun, 21 Mar 2027 08:52:14 GMT,而max-age指定的是生命时长秒数315360000。

  区别在于Expires是 HTTP/1.0 的中的标准,而max-age是属于Cache-Control的内容,是 HTTP/1.1 中的定义的。但为了想向前兼容,这两个属性仍然要同时存在。

  但有一种更倾向于使用max-age的观点认为Expires过于复杂了。例如上面的例子Sun, 21 Mar 2027 08:52:14 GMT,如果你在表示小时的数字缺少了一个0,则很有可能出现出错;如果日期没有转换到用户的正确时区,则有可能出错。这里出错的意思可能包括但不限于缓存失效、缓存生命周期出错等。

5.3、Etag VS. Last-Modified

  Etag和Last-Modified都可以用于对资源进行验证,而Last-Modified顾名思义,表示资源最后的更新时间。

  我们把这两者都成为验证器(Validators),不同的是,Etag属于强验证(Strong Validation),因为它期望的是资源字节级别的一致;而Last-Modified属于弱验证(Weak Validation),只要资源的主要内容一致即可,允许例如页底的广告,页脚不同。

  根据RFC 2616标准中的13.3.4小节,一个使用HTTP 1.1标准的服务端应该(SHOULD)同时发送Etag和Last-Modified字段。同时一个支持HTTP 1.1的客户端,比如浏览器,如果服务端有提供Etag的话,必须(MUST)首先对Etag进行Conditional Request(If-None-Match头信息);如果两者都有提供,那么应该(SHOULD)同时对两者进行Conditional Request(If-Modified-Since头信息)。如果服务端对两者的验证结果不一致,例如通过一个条件判断资源发生了更改,而另一个判定资源没有发生更改,则不允许返回304状态。但话说回来,是否返回还是通过服务端编写的实际代码决定的。所以仍然有操纵的空间。

5.4、max-age=0 VS. no-cache

  max-age=0是在告诉浏览器,资源已经过期了,你应该(SHOULD)对资源进行重新验证了;而no-cache则是告诉浏览器在每一次使用缓存之前,你必须(MUST)对资源进行重新验证。

  区别在于,SHOULD是非强制性的,而MUST是强制性的。在no-cache的情况下,浏览器在向服务器验证成功之前绝不会使用过期的缓存资源,而max-age=0则不一定了。虽然理论上来说它们的效果应该是一致的。

5.5、public VS. private

  要知道从服务器到浏览器之间并非只有浏览器能够对资源进行缓存,服务器的返回可能会经过一些中间(intermediate)服务器甚至甚至专业的中间缓存服务器,还有CDN。而有些请求返回是用户级别、是私人的,所以你可能不希望这些中间服务器缓存返回。此时你需要将Cache-Control设置为private以避免暴露。

6、缓存实战

  前面写了很多缓存的基础知识,那么如何设计一个可靠的缓存规则,这个其实得根据你的实际需求而定。

  比如某个资源永远不会改变,比如某些第三方库(一般都放CDN做优化了),或者某些图片,比如百度的图片,就让它们永久缓存着吧,设置一个最大的max-age

Cache-Control: max-age=31536000

其他的资源可根据下面这张决策树来进行设置

완벽한 http 캐싱 전략을 설계하는 방법

7、memory cache

완벽한 http 캐싱 전략을 설계하는 방법

  “内存缓存”中主要包含的是当前文档中页面中已经抓取到的资源。例如页面上已经下载的样式、脚本、图片等。我们不排除页面可能会对这些资源再次发出请求,所以这些资源都暂存在内存中,当用户结束浏览网页并且关闭网页时,内存缓存的资源会被释放掉。

  这其中最重要的缓存资源其实是preloader相关指令(例如)下载的资源。总所周知preloader的相关指令已经是页面优化的常见手段之一,而通过这些指令下载的资源也都会暂存到内存中。根据一些材料,如果资源已经存在于缓存中,则可能不会再进行preload。

  需要注意的事情是,内存缓存在缓存资源时并不关心返回资源的HTTP缓存头Cache-Control是什么值,同时资源的匹配也并非仅仅是对URL做匹配,还可能会对Content-Type,CORS等其他特征做校验
这个应该是浏览器做的一种优化,缓存也只是暂时的。

8. 브라우저는 Cache-Control 헤더가 유효하지 않도록 제한할 수 있습니다

완벽한 http 캐싱 전략을 설계하는 방법

권장 튜토리얼: HTTP 중국어 개발 매뉴얼

위 내용은 완벽한 http 캐싱 전략을 설계하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 cnblogs.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제