有关Nginx 200 OK (FROM CACHE) 与 304 NOT MODIFIED

来源:互联网 发布:电信软件市场 编辑:程序博客网 时间:2024/05/01 01:20

HTTP缓存基础

协商缓存

  • If-Modified-Since/Last-modified: 服务器程序检查请求头(request header)里面的(If-modified-Since),如果最后修改时间相同(例如静态文件的Modified time 通过shell ls -l可以查看)则返回304,否则给返回头(response header)添加last-Modified并且返回数据(response body)。

  • If-None-Match/Etag:服务器程序检查检查请求头(request header)里面的if-none-match的值与当前文件的内容通过hash算法(例如 nodejs: cryto.createHash('sha1'))生成的内容摘要字符对比,相同则直接返回304,否则给返回头(response header)添加etag属性为当前的内容摘要字符,并且返回内容。

强缓存(也就是from cache)

  • 如果设置了Expires(XX时间过期)或者Cache-Control(http1.0不支持)(经历XX时间后过期)且没有过期,命中cache的情况下,from cache不去发出请求。如果强刷(如ctrl+r)会发起请求,但是如果没有修改会返回304内容未修改,如果已经改变则返回新内容。

  • expires/cache-control 虽然是强缓存,但用户主动触发的刷新行为,还是会采用缓存协商的策略,主动触发的刷新行为包括点击刷新按钮、右键刷新、f5刷新、ctrl+f5刷新等。

  • 当然如果在控制台里面选中了disable cahce则无论如何都会请求最新内容(304协商缓存、强缓存都无效),因为
    1.不会检查本地是否有缓存。
    2.请求头信息(request header)既没有If-Modified-Since也没有If-None-Match来让服务端判断。

地址栏输入的地址按下回车键,该地址页面请求(仅仅是该url)的request header都会带上cache-contro:max-age=0,所以不会命中强缓存(参考:How do I stop Chrome sending Cache-control: max-age=0 when I hit enter?),但是通过链接点击的地址会命中缓存


这里对于浏览器的缓存机制简单了解

浏览器的缓存机制分为两块,也就是规范中的4.2. Freshness 和 4.3. ValidationFreshnessCache Control与Expires是一组,他们是用来进行Freshness验证,也就是提供客户端检测文件是否足够新鲜,可以无需向服务端发起Validation请求就能保证并未过期可以直接使用。所有的from cache的请求实际上都是由于浏览器认为本地的缓存资源足够新鲜,所以无需额外请求而直接使用。具体的判断方法可以参考协议,实际上就是根据本地的时间和服务器返回头的约定信息进行对比验证。历史问题为何有两个参数而不是一个参数则是由于历史原因,在HTTP1.0中定义的是Expires,Expires的值是一个明确的过期时间,而后来使用中发现一旦客户端时间与服务器时间不一致就会引发很多缓存问题。因此在HTTP 1.1中新添加了Cache Control,实现了更优的文件过期声明,比如max-age配置,是一个timespan,告知客户端这个文件多长时间不会过期而不是直接告知过期时间。ValidationLast-Modified和ETag则是另一组控制信息,他们用来实现Validation。他们的职责是在本地缓存被浏览器判断可能不够新鲜的时候,会用这两组信息向服务器请求数据,如果服务器内容没有改变,那么约定服务器会返回304 HTTP Code表明这个缓存可以直接使用,无需重新拉取,而一旦服务器内容改变了就会返回200,同时返回新的文件内容。历史问题至于为何有两组字段来解决这个问题依然是历史问题,在HTTP 1.0中约定的是Last-Modified,他代表的含义是文件最后一次修改的时间,那么这种约定带来的问题是一旦内容是动态生成的,这个时间在服务器端不一定可以正确的生成,其次是Last-Modified只有秒级的精度,如果在一秒内有一次以上的文件修改,这样的缓存就会造成额外的问题。因此HTTP1.1中新引入了ETag,他的实现不尽相同,对于动态内容,常规做法是对动态内容做HASH计算,作为ETAG返回,对于静态资源,一般是使用inode+mtime进行计算。额外的问题ETag也有他自己的问题,所以经常在使用中会关闭ETag。举例来说,同一个文件在不同物理机上的inode是不同的,这就导致了在分布式的Web系统中,当访问落在不同的物理机上时会返回不同的ETag,进而导致304失效,降级为200请求。解决办法也有从ETag算法中剥离inode,只是使用mtime,但是这样实际上和Last-Modified就一样了。当然你也可以额外的做一些改进,使ETag对静态资源的算法也是通过hash计算的。不过由于一般我们会使用CDN技术,因此集群部署中的ETag问题并不会造成太大的影响,所以折腾的人也不太是很多。总结总结一下,ETag的设置并不会影响Freshness验证,Freshness验证会和浏览器策略以及Cache Control与Expires有关。

对于200 OK 和304 NOT MODIFIED
,两者触发的时机有什么区别呢?200 OK (from cache) 是直接点击链接访问,输入网址按回车访问也能触发;而 304 Not Modified 是刷新页面时触发,或是设置了长缓存、但 Entity Tags 没有移除时触发。这是经过查阅资料得出的结论

0 0
原创粉丝点击