很久没有写博客了,趁现在也快过年,最近项目不是很忙,写一篇博客做为2018年的开始,重拾刚毕业的几年前写博客的冲动。http协议是每个程序猿应该需要知道的东西,不管是前端人员还是后端人员,以前在上家公司的时候,因为项目的需要,曾经专门去了解过cdn,其中就需要掌握http协议中的缓存相关知识。

http缓存流程图

直接上图,后文会具体的叙述

http协议

在介绍http缓存之前,作为知识铺垫,先简单介绍下http报文。http报文就是客户端(如浏览器)和web服务器通信时发送和响应的的数据。

http请求由三部分组成分别是请求行、消息报头、请求正文

http 响应也是由三个部分组成,分别是:状态行、消息报头、响应正文

与缓存相关的信息,都包含在消息报头(header)中。不了解http协议的,先补充下http协议的知识,google搜索一大堆,本文就直接略过了。

http响应头中相关缓存字段

随便请求一个网页,这里我们打开百度首页,打开浏览器的调试工具

Expires

Expires的值为web服务器返回的到期时间(GMT 格林威治时间),浏览器下次请求时间小于服务器返回的时间则浏览器直接从缓存中获取数据,而不用再次发送请求。

Cache-Control

Cache-Control常见的取值有private、public、no-cache、max-age,no-store

private:客户端可以缓存

public :客户端和代理服务器都可缓存

max-age=<seconds>:缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)

no-cache:这个很容易让人产生误解,使人误以为是响应不被缓存,实际上Cache-Control:no-cache是会被缓存的,

                 只不过每次在向浏览器提供响应数据时,浏览器每次都要向服务器发送请求,由服务器来决策来评估缓存的有效性

no-store: 所有内容都不缓存(真真的不缓存)

更多详细的Cache-Control的取值参考MDN文档https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control

强制缓存:Expires和Cache-Control区别

Expires和Cache-control称为强制缓存,都是在缓存未失效时,浏览器不向服务端发起请求,直接从缓存中取数据。也许你会有疑问,都是一样的作用,为什么要两个都存在呢?

Expires是上古时代Http1.0的东西了,现在默认浏览器均默认使用的是Http1.1了,所以它的作用是可以基本忽略。Expires有一个缺点,就是返回的时间的服务器的绝对时间,用本地时间和服务端时间比较是否过期,是不严谨的,用户是可以随便修改本地时间的,那这样缓存随时可以过期,所以被Cache-Control:max-age=<seconds>取代了,在http1.1中Cache-Control优先级高于Expires。软件工程的特点是向下兼容,Expires一直就没有抛弃,对于使用http1.0协议的浏览器仍然有作用。

Last-Modified

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

Etag

服务器响应请求时,告诉客户端(浏览器)当前请求的资源在服务器标识(Etag的生成算法由服务器决定,不同的web服务器生成etag的算法可能还不一样,Http协议并没有要求etag的生成规则,如文件小的时候可以使用md5sum sha1sum,或者根据文件修改时间,文件大小,文件inode文件属性综合生成,这里不做详细叙述),我们可以将其理解为一个资源的唯一标识,只要文件发生变化Etag的值也变化。

对比缓存:Last-Modified/If-Modified-Since和Etag/If-None-Match

Last-Modified和Etag称为对比缓存,所谓对比缓存,顾明思议,就是需要服务器来比较判断,来告诉客户端(浏览器)是否可以使用本地缓存,对比缓存生效时,服务器返回给客户端(浏览器)的Http Code为304,服务器只是返回的http header信息,并无响应正文,客户端通过服务器返回的状态码304,知道本地缓存并无修改,可以直接使用本地缓存,这样大大的较少的客户端请求响应时间。

对比缓存大致流程是这样的,当浏览器请求服务器的某资源时, 服务器得到资源的最后修改时间(Last-Modified)或根据一定的算法生成资源的标识(Etag),并将Last-Modified或If-Modified-Since返回给浏览器,浏览器把Last-Modified或Etag 和 资源内容同时缓存在本地,当下次再次向服务器请求此资源时,会将If-Modified-Since: Mon, 07 Nov 2016 07:51:11 GMT 或If-None-Match: xxxxxxx"的请求头把发送给服务器,服务器再次计算资源的Last-Modified或Etag,如果和客户端传来的值比较不相同,则表明资源发生了变化,则给浏览器返回Http Code 200。并将资源内容返回给浏览器,如果相同表示没有变化就给浏览器返回Http Code 304 ,并不需要返回资源内容给浏览器。

对于浏览器来说的话,一般会在强制缓存过期的情况下(或者按F5刷新,不同的浏览器可能不一样,firefox是按F5)如果资源原先的响应header中带有Last-Modified和Etag的话,浏览器请求时会在请求header中带上If-Modified-Since和If-None-Match。

Last-Modified和Etag区别

在这里,也许你可能会问,通过Last-Modified就可以知道资源内容是否发生了变化,为什么还需要Etag呢,这不是多此一举吗?,主要原因Etag解决了Last-modified没能解决的问题,Etag比Last-Modified更加严谨。

1.一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了
      2.某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断

3.如需要对动态生成的内容做缓存,那就可以用etag来控制缓存了

需要注意的是,如果同时有Last-Modified和Etag存在,在发送请求时,浏览器会一次性的将这两个值都发给服务器,没有优先级,服务器是都比较,还是只比较一个,不同的web服务器可能比较逻辑不一样吧。具体的不深究了。

Http请求头中Cache-Control: no-cache的意义

一般按ctrl+f5强制刷新时,请求头里面都带有Cache-Control: no-cache,其实这是跳过本地的强制缓存和告诉服务器跳过对比缓存,也就是重新请求资源了。对于前端同学在通过GET请求后端API接口时,在ajax的请求头中统一带上Cache-Control: no-cache。

总结

1. 对于强制缓存,服务器通知浏览器一个缓存时间,在缓存时间内,下次请求,直接用缓存,不在时间内,执行对比缓存策略。

2. 对于对比缓存,将缓存信息中的Etag和Last-Modified通过请求发送给服务器,由服务器校验,返回304状态码时,浏览器直接使用缓存。

http缓存知多少的更多相关文章

  1. 知乎技术分享:从单机到2000万QPS并发的Redis高性能缓存实践之路

    本文来自知乎官方技术团队的“知乎技术专栏”,感谢原作者陈鹏的无私分享. 1.引言 知乎存储平台团队基于开源Redis 组件打造的知乎 Redis 平台,经过不断的研发迭代,目前已经形成了一整套完整自动 ...

  2. 智能dns或CDN应用中,如何很好的解决DNS缓存问题? - 知乎

    智能dns或CDN应用中,如何很好的解决DNS缓存问题? - 知乎 LISP路由器

  3. (转)面试前必知Redis面试题—缓存雪崩+穿透+缓存与数据库双写一致问题

    背景:redis问题在面试过程中经常被问到,对于常见问题一定不能放过. 面试前必知Redis面试题—缓存雪崩+穿透+缓存与数据库双写一致问题 一.缓存雪崩 1.1什么是缓存雪崩? 如果缓存数据设置的过 ...

  4. Web 技术人员需知的 Web 缓存知识(转)

    最近的译文距今已有4年之久,原文有一定的更新.今天踩着前辈们的肩膀,再次把这篇文章翻译整理下.一来让自己对web缓存的理解更深刻些,二来让大家注意力稍稍转移下,不要整天HTML5, 面试题啊叨啊叨的~ ...

  5. Web 技术人员需知的Web 缓存知识

    最近的译文距今已有4年之久,原文有一定的更新.今天踩着前辈们的肩膀,再次把这篇文章翻译整理下.一来让自己对web缓存的理解更深刻些,二来让大家注意力稍稍转移下,不要整天HTML5, 面试题啊叨啊叨的~ ...

  6. Web开发人员需知的Web缓存知识

    最近的译文距今已有4年之久,原文有一定的更新.今天踩着前辈们的肩膀,再次把这篇文章翻译整理下.一来让自己对web缓存的理解更深刻些,二来让大家注意力稍稍转移下,不要整天HTML5, 面试题啊叨啊叨的~ ...

  7. Android必知必会--GreenDao缓存

    Github版 CSDN版 本篇文章不是介绍GreenDao的配置和基础使用,记录一下GreenDao缓存的问题,帮助遇到同样问题的朋友找到原因和方法,下面是示例: 场景重现 //第一次查询 List ...

  8. 面试前必知Redis面试题—缓存雪崩+穿透+缓存与数据库双写一致问题

    今天来分享一下Redis几道常见的面试题: 如何解决缓存雪崩? 如何解决缓存穿透? 如何保证缓存与数据库双写时一致的问题? 一.缓存雪崩 1.1什么是缓存雪崩? 回顾一下我们为什么要用缓存(Redis ...

  9. Web 开发人员需知的 Web 缓存知识

    今天踩着前辈们的肩膀,再次把这篇文章翻译整理下.一来让自己对web缓存的理解更深刻些,二来让大家注意力稍稍转移下,不要整天HTML5, 面试题啊叨啊叨的~~ 什么是Web缓存,为什么要使用它? Web ...

随机推荐

  1. Angular : 响应式编程, 组件间通信, 表单

    Angular 响应式编程相关 ------------------------------------------------------------------------------------ ...

  2. thinkphp5一些文件夹用法

    一.vendor通常放一些第三方的文件,如短信.支付宝等.用法: 1.在vendor中建一个文件夹: 2.在文件夹中新建一个类:主要命名空间(没有vendor ):如下面: 3.在控制器中调用,除了通 ...

  3. Java基础——继承和多态

    面向对象的编程允许从已经存在的类中定义新的类,这称为继承. 面向过程的范式重点在于方法的设计,而面向对象的范式将数据和方法结合在对象中.面向对象范式的软件设计着重于对象以及对象上的操作.面向对象的方法 ...

  4. 宝塔漏洞 XSS窃取宝塔面板管理员漏洞 高危

    宝塔是近几年刚崛起的一款服务器面板,深受各大站长的喜欢,windows2003 windows2008windosws 2012系统,linux centos deepin debian fedora ...

  5. linux进程篇 (一) 进程的基本概念

    进程是系统资源分配的最小单位. 1.创建和执行 父进程通过 fork 系统调用创建子进程, 子进程被创建后,处于创建状态. linux为子进程配置数据结构,如果内存空间足够,子进程就在内核中就绪,成为 ...

  6. 141. 环形链表 LeetCode报错:runtime error: member access within null pointer of type 'struct ListNode'

    /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode ...

  7. SIMD数据并行(四)——三种结构的比较

    在计算机体系中,数据并行有两种实现路径:MIMD(Multiple Instruction Multiple Data,多指令流多数据流)和SIMD(Single Instruction Multip ...

  8. java.lang.NoClassDefFoundError 错误解决思路

    Process: com.oppo.reader, PID: 20472 java.lang.NoClassDefFoundError: com.zhangyue.iReader.PDF2.ui.PD ...

  9. ASCII码、HEX、字符、BCD 等等 基础知识思考

    每每遇到这些问题就要想个半天,想不明白还不舒服,今天特别把所想整理下避免以后再次进入思想漩涡!!! 计算机存储和传输都是以字节为单位        1 bit     = 1  二进制数据       ...

  10. SharePoint显示错误信息

         在SharePoint项目中,一般如果发生错误,SharePoint会弹出它自定义的报错页面,一般就显示"Something went wrong",如果光是看这一句话, ...