文章目录
HTTP缓存
HTTP 缓存的好处?
- 减少亢余的数据传输,节约资源
- 缓解服务器压力,提高网站性能
- 加快客户加载网页的速度
不想使用缓存的几种方式
- Ctrl + F5强制刷新,都会直接向服务器提取数据
- 按F5刷新或浏览器的刷新按钮,默认加上Cache-Control:max-age=0,即会走协商缓存
浏览器的缓存分类
- 强缓存 200 (from memory cache)和200 (from disk cache)
- 协商缓存 304 (Not Modified)
刷新操作的缓存策略
- 正常操作:强制缓存有效,协商缓存有效
- 手动刷新:强制缓存失效,协商缓存有效
- 强制刷新:强制缓存失效,协商缓存失效
缓存流程
强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回304,继续使用缓存,主要过程如下:
强制缓存
如果启用了强缓存,请求资源时不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的network中看到请求返回的200状态码,并在状态码的后面跟着from disk cache 或者from memory cache关键字。两者的差别在于获取缓存的位置不一样。
- Pragma:在 http1.1 中被遗弃
- Cache-Control:http1.1 时出现的header信息。设置过期时间(绝对时间、时间点),超过了这个时间点就代表资源过期。但是用户的本地时间是可以自行调整的,所以会出现问题。
- max-age=x(单位秒):缓存内容将在x秒后失效,如
Cache-Control:max-age=36000
- no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
- no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
- private:所有内容只有客户端可以缓存,Cache-Control的默认取值
- public:所有内容都将被缓存(客户端和代理服务器都可缓存)
- max-age=x(单位秒):缓存内容将在x秒后失效,如
- Expires:是http1.0的规范,它的值是一个绝对时间的GMT格式的时间字符串。设置过期时长(相对时间、时间段),指定一个时间长度,跟本地时间无关,在这个时间段内缓存是有效的。
- 同在Response Headers中
- 同为控制缓存过期
- 已被Cache-Control代替
注意:生效优先级为(从高到低):Pragma > Cache-Control > Expires 。
Pragma
在 http1.1 中被遗弃。
Cache-Control
第一步:浏览器首次发起请求,缓存为空,服务器响应:
浏览器缓存此响应,缓存寿命为接收到此响应开始计时 100s 。
第二步:10s 过后,浏览器再次发起请求,检测缓存未过期,浏览器计算 Age: 10 ,然后直接使用缓存,这里是直接去内存中的缓存,from disk 是取磁盘上的缓存:
第三步:100s 过后,浏览器再次发起请求,检测缓存过期,向服务器发起验证缓存请求。如果服务器对比文件已发生改变,则如 1;否则不返回文件数据报文,直接返回 304:
Expires
Expires是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求的结果缓存的到期时间,即再次发送请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。
Expires是HTTP/1.0的字段,但是现在浏览器的默认使用的是HTTP/1.1,那么在HTTP/1.1中网页缓存还是否由Expires控制?到了HTTP/1.1,Expires已经被Cache-Control替代,原因在于Expires控制缓存的原理是使用客户端的时间与服务端返回的时间做对比,如果客户端与服务端的时间由于某些原因(时区不同;客户端和服务端有一方的时间不准确)发生误差,那么强制缓存直接失效,那么强制缓存存在的意义就毫无意义。
协商缓存
协商缓存(对比缓存)就是由服务器来确定缓存资源是否可用,所以客户端与服务器端要通过某种标识来进行通信,从而让服务器判断请求资源是否可以缓存访问,这主要涉及到下面两组header字段。这两组搭档都是成对出现的,即第一次请求的响应头带上某个字段(Last-Modified或者Etag),则后续请求则会带上对应的请求字段(If-Modified-Since或者If-None-Match),若响应头没有Last-Modified或者Etag字段,则请求头也不会有对应的字段。
注意:Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。
ETag/If-None-Match
Etag
Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),如下:
If-None-Match
If-None-Match是客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。服务器收到该请求后,发现该请求头中含有If-None-Match,则会根据If-None-Match的字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200,如下:
注意:Etag/If-None-Match优先级高于Last-Modified/If-Modified-Since,同时存在则只有Etag/If-None-Match生效。
Last-Modified/If-Modified-Since
Last-Modified
Last-Modified是服务器响应请求时,返回该资源文件在服务器最后被修改的时间,如下:
If-Modified-Since
If-Modified-Since则是客户端再次发起该请求时,携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。服务器收到该请求,发现请求头含有If-Modified-Since字段,则会根据If-Modified-Since的字段值与该资源在服务器的最后被修改时间做对比,若服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件,如下:
常见问题
问题一:为什么要有Etag?
你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:
一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
某些服务器不能精确的得到文件的最后修改时间。
问题二:如果什么缓存策略都没设置,那么浏览器会怎么处理?
如果什么缓存策略都没设置,没有Cache-Control也没有Expires,对于这种情况,浏览器会采用一个启发式的算法(LM-Factor),通常会取响应头中的 Date 减去 Last-Modified 值的 10% (不同的浏览器可能不一样)作为缓存时间。
请求方法
截止到HTTP1.1共有下面几种方法:
方法 | 描述 |
---|---|
GET | GET请求会显示请求指定的资源。一般来说GET方法应该只用于数据的读取,而不应当用于会产生副作用的非幂等的操作中。它期望的应该是而且应该是安全的和幂等的。这里的安全指的是,请求不会影响到资源的状态 |
POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改 |
PUT | PUT请求会身向指定资源位置上传其最新内容,PUT方法是幂等的方法。通过该方法客户端可以将指定资源的最新数据传送给服务器取代指定的资源的内容 |
PATCH | PATCH方法出现的较晚,它在2010年的RFC 5789标准中被定义。PATCH请求与PUT请求类似,同样用于资源的更新。二者有以下两点不同:1.PATCH一般用于资源的部分更新,而PUT一般用于资源的整体更新。2.当资源不存在时,PATCH会创建一个新的资源,而PUT只会对已在资源进行更新 |
DELETE | DELETE请求用于请求服务器删除所请求URI(统一资源标识符,Uniform Resource Identifier)所标识的资源。DELETE请求后指定资源会被删除,DELETE方法也是幂等的 |
OPTIONS | 允许客户端查看服务器的性能 |
CONNECT | HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器 |
HEAD | 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头 |
TRACE | 回显服务器收到的请求,主要用于测试或诊断 |
头参数
常见请求头
名称 | 作用 |
---|---|
Authorization | 用于设置身份认证信息 |
User-Agent | 用户标识,如:OS和浏览器的类型和版本 |
If-Modified-Since | 值为上一次服务器返回的 Last-Modified 值,用于确认某个资源是否被更改过,没有更改过(304)就从缓存中读取 |
If-None-Match | 值为上一次服务器返回的 ETag 值,一般会和If-Modified-Since 一起出现 |
Cookie | 已有的Cookie |
Referer | 表示请求引用自哪个地址,比如你从页面A跳转到页面B时,值为页面A的地址 |
Host | 请求的主机和端口号 |
常见响应头
名称 | 作用 |
---|---|
Date | 服务器的日期 |
Last-Modified | 该资源最后被修改时间 |
Transfer-Encoding | 取值为一般为chunked,出现在Content-Length不能确定的情况下,表示服务器不知道响应版体的数据大小,一般同时还会出现Content-Encoding 响应头 |
Set-Cookie | 设置Cookie |
Location | 重定向到另一个URL,如输入浏览器就输入baidu.com回车,会自动跳到 https://www.baidu.com ,就是通过这个响应头控制的 |
Server | 后台服务器 |
状态码
HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:
分类 | 分类描述 |
---|---|
1xx | 信息,服务器收到请求,需要请求者继续执行操作 |
2xx | 成功,操作被成功接收并处理 |
3xx | 重定向,需要进一步的操作以完成请求 |
4xx | 客户端错误,请求包含语法错误或无法完成请求 |
5xx | 服务器错误,服务器在处理请求的过程中发生了错误 |
一般我们只需要知道几个常见的就行,比如 200,400,401,403,404,500,502。
请求流程
说下浏览器请求一个网址的过程?
- 首先通过DNS服务器把域名解析成IP地址,通过IP和子网掩码判断是否属于同一个子网
- 构造应用层请求http报文,传输层添加TCP/UDP头部,网络层添加IP头部,数据链路层添加以太网协议头部
- 数据经过路由器、交换机转发,最终达到目标服务器,目标服务器同样解析数据,最终拿到http报文,按照对应的程序的逻辑响应回去
常见问题
http1.1和http2的区别
HTTP1.1
- 持久连接
- 请求管道化
- 增加缓存处理(新的字段如cache-control)
- 增加 Host 字段、支持断点传输等
HTTP2.0
- 二进制分帧
- 多路复用(或连接共享)
- 头部压缩
- 服务器推送
HTTP 和HTTPS的区别
(1)HTTPS 协议需要到 CA 申请证书,一般免费证书较少,因而需要一定费用。
(2)HTTP 是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 SSL 加密传输协议。
(3)HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
(4)HTTP 的连接很简单,是无状态的;HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。
对称加密和非对称加密
对称密钥加密是指加密和解密使用同一个密钥的方式,这种方式存在的最大问题就是密钥发送问题,即如何安全地将密钥发给对方
;
而非对称加密是指使用一对非对称密钥,即公钥
和私钥
,公钥可以随意发布,但私钥只有自己知道。发送密文的一方使用对方的公钥进行加密处理,对方接收到加密信息后,使用自己的私钥进行解密。
由于非对称加密的方式不需要发送用来解密的私钥,所以可以保证安全性
;但是和对称加密比起来,它比较慢
,所以我们还是要用对称加密来传送消息,但对称加密所使用的密钥我们可以通过非对称加密的方式发送出去。
常见状态码
1×× : 请求处理中,请求已被接受,正在处理
2×× : 请求成功,请求被成功处理 200 OK
3×× : 重定向,要完成请求必须进行进一步处理 301 : 永久性转移 302 :暂时性转移 304 :已缓存
4×× : 客户端错误,请求不合法 400:Bad Request,请求有语法问题 403:拒绝请求 404:客户端所访问的页面不存在
5×× : 服务器端错误,服务器不能处理合法请求 500 :服务器内部错误 503 :服务不可用,稍等
Session、Cookie 的区别
- session 在服务器端,cookie 在客户端(浏览器)
- session 默认被存储在服务器的一个文件里(不是内存)
- session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id)
- session 可以放在 文件、数据库、或内存中都可以。
- 用户验证这种场合一般会用 session