- 相关术语
- 包: 全能性术语
- 帧: 用于表示数据链路层的单位
- 数据包: 是ip 等网络层以上的分层中包的单位
- 段: TCO数据流的信息
- 数据在传输过程中,从发送者到接手者,从上层到下层,再冲下层到上层,会涉及到 装包,拆包,每层都会装上或者取下各自的头部信息
应用层
HTTP
MIME
- MIME(Multipurpose Internet Mail Extensions): 多用途互联网邮件扩展类型.用途在于设定某种扩展名的文件用一种特殊的应用程序所打开
特地的文件 | 对应的MIME类型 |
---|---|
RTF文本rtf | appliation/rtf |
普通文本txt | txt/plain |
gif图形 | image/git |
au声音文件 | audio/basic |
avi文件 | video/x-msvideo |
http协议的特点
- 灵活: 允许客户端和服务端传输任意类型的对象
- 无连接: 每次连接只能处理一个请求,处理完客户端请求并结束应答之后立即断开连接
- 无状态: 对于事务处理无记忆能力,服务器不知道客户端的状态
HTTP中的请求报文
-
结构分为: 请求行,请求头,空行,请求体
-
请求行:
中间都由空隔分开
GET /info HTTP/1.1- 请求方法: GET POST PUT DELETE
- URI: /info
- HTTP协议版本组成
-
请求头: 由key-value对组成,通过冒号分隔,每行一对
- 常见的有:
- User-Agent: 用户代理信息(如书记型号,mac等)
- Accept: 客户端可以识别的内容类型列表,如 text/htl,application/xhtml+xml ,application/xm
- Accept-Language: 客户端可以接受的自然语言(中文英文等): zh-CN,zh;q=0.8,en;
- Accept-Encoding: 客户端可以接受的编码压缩格式: gzipdeflate,sdch,r
- Host: 请求的主机名(既服务器的域名或者ip)
- Connection: 连接方式
- close: 告诉服务器,完成本次连接之后,断开连接
- keep-alive: 告诉服务器,完成本次请求响应之后,保持连接,等待后续请求
-
空行,代表不再有请求头
-
请求体: 只有当请求方法为post的时候才会有数据,其他时候都没有
HTTP的响应报文
-
结构分为: 状态行,响应头,空行和响应体组成
-
状态行: **HTTP/1.1 200 ok **
- 协议版本
- 状态码
- 状态码描述符
- 回车|换行符 组成
-
响应头: 与请求头类似,常见的有:
- server: 请求的原始服务器的信息
- Date: 服务器日期
- Connectio: 连接方式
- close: 连接已关闭
- keep-alive: 连接已保持,在等待本次连接的后续请求
- Cache-Control: 用于缓存控制
- Expires: 过期时间,也用于缓存控制
-
空行: 通知浏览器,不再有响应头
-
响应体: 既返回的数据
HTTP Methods
- GET: 用于获取数据,通过url传递参数
- POST: 通常用于上传数据,通过Request中的请求体
- PUT: 用于资源更新
- DELETE: 通常用于删除资源
HTTP的状态码:
- 1xx: 表示请求已经接受,继续处理
- 2xx: 成功-表示请求已被成功处理
- 200: 请求成功
- 204: No Content: 没有新文档,浏览器可以使用原先的文档
- 206: Partial Content: 客户端发送了一个带有range 头的get 请求
- 3xx : 重定向,若要完成请求,必须更进一步的操作
- 302: 该URL已经过期,使用新的url
- 304: 提示浏览器可以使用之前的数据
- 4xx: 客户端错误,请求有语法错误或者请求无法实现
- 400: Bad Request: 客户端请求有语法错误
- 401: 未授权,通常与Authentication请求头一起使用
- 403: 禁止方位: 所请求的资源禁止访问
- 404: 资源不存在
- 5xx: 服务端错误
- 500: 服务器错误
- 503: 服务器挂了
HTTP的cookie
- cookie保存在浏览器端
- Cookie的类别:
- Session Cookie: 只在会话期内有效,当关闭浏览器的时候,会被浏览器立即删除,
- 设置方式: 过期时间不设置即可
- Persistent Cookie: 持久化cookie,长期在用户会话中生效
- 设置方式: 持久化时间与过期时间相关
- Secure Cookie: https状态下的cookie,在传输过程中,始终被加密
- Session Cookie: 只在会话期内有效,当关闭浏览器的时候,会被浏览器立即删除,
- Cookie的用途:
- 会话管理: 记录用户的登录状态,保存用户的个性化信息
- Cookie和Session的区别:
- 每次HTPP请求都会发送相应的Cookie到服务端,实现Session跟踪可以用Cookie实现
- Session复写的方法:
- 通过Cookie
- 通过Uril复写
- 通过form表单的隐藏域
- Session是服务端保存的一个数据结构,用来跟踪用户状态,可以存放在其他文件中
- Cookie是客户端用来保存用户信息的一种机制,使得HTTP状态化
HTTP Cache
- Http Cache的定义: 是指一个文件在服务器和客户都拿之间的副本,缓存会根据请求的内容保存输出内容到副本中,若下一个请求到来,根据相关请求头和响应头的设置决定 是否直接使用缓存,还是校验是否使用缓存,还是获取到最新的数据
- Web缓存的类型:
- 数据库缓存: redis,memcached等
- 服务端缓存:
- 代理服务器
- CDN缓存: 也叫做网关缓存,反向代理缓存
- 浏览器端缓存:依据请求头和响应头等相关字段,决定
- WEB应用层缓存: 指的是代码层面
缓存相关的http首部字段
-
通用首部字段:
- Cache-Control: 控制缓存的行为,http1.0的一遗留物 当使用no-cache的时候代表禁用缓存
-
请求首部字段:
- if-match: 比较etag是否一致
- if-none-match: 比较etag是否不一致
- if-Modified-since: 比较资源更新的时间是否一致
- if-unmodified-since: 比较资源更新的时间是否不一致
-
响应首部字段:
- etag: 资源的匹配信息
-
实体首部字段:
- expires: http1.0的遗留物,表示实体过期时间
- Last-Modified: 该资源的最后一次修改时间
缓存方式
-
http1.0 时代,可以使用pragma和expires来规范,至今保留是为了向下兼容,expires过期时间是依据服务器时间而定
-
Cache-Control:
- 无法保证与客户端时间统一的问题,Http1.1 引入了Cache-Control定义缓存过期时间
- 注意:
- Cache-Control: 具体精确到秒
- 值的形式是通过当前时间的n 秒,而不是具体的时间,这样就解决了expires 服务器和客户端时间不一致的问题
- 请求首部:
- no-cache: 表示i代理服务器不直接使用缓存,要求向原服务器发起请求
- no-store: 所有内容都不会保存到缓存或者其他临时文件中
- max-age=3 表示在这之后的 3秒内,都能直接使用
- min-fresh=3 表示客户端希望接受在3秒内更新过的资源
- no–transform: 告知服务器,客户端希望获取到的数据,不要做任何转换操作
- only-if-cached: 告知代理服务器,如果有缓存,则把缓存给我,不需要向源服务器发起请求
- 响应首部:
- pubic: 表示任何请情况下都缓存资源,即使是https
- private: 表明除客户端外,数据其他(如代理服务器)不可缓存
- no-cache: 指不可缓存,每次都需要发起请求
- no-store: 所有内容都不会保存到缓存中
- no-transform:缓存时不要对数据进行任何修饰
- only-if-cached: 告知代理服务求,若客户端自身有缓存,则不需要发起请求
- must-revalidate: 必须向资源服务器发起验证请求,若请求失败返回504
- max-age=3s : 告知客户端,该资源在未来3秒内都是最新的,无需发起请求
- s-max-age: 与max-age一致,不同在于只能使用共享缓存
缓存校验字段
-
缓存首部字段能让客户端决定是否需要向服务器发起请求,如过期时间等信息,具体则是如下字段实现的
-
服务端:
- Last-Modified: 服务器返回的字段,表示最近一次修改的时间,客户端收到之后会在资源上标记该信息,但客户端发起请求时,会携带
-
客户端:
- If-Modifed-Since: 匹配则返回304
- If-Unmodifed-since: 若服务端Last-Modified没有匹配,则服务端应该返回412同时携带所有的数据返回
-
服务端:
- ETAG: 为了解决Last-modifed存在不精确的问题(既ABA,或者1秒内更新多次的问题),HTTP1.1推出了ETAG作为头部字段,客户端会保留ETAG.并在下一次请求时一并带过去
-
客户端:
-
If-Match: ETag-Vaue 服务器若没有匹配到ETag或者收到了*指,但是没有资源,返回412
缓存方式 服务端 客户端 缺点 Expires/Pragma Expires|Pragma Expires Http1.0的产物,时间是相对于服务器而言 Cache-Control CacheControl Cache-Control 无法向下兼容, Last-Modified Last-Modified If-Modified-Since| If-Unmodified-Since 每次请求都会校验,相同304,不同200,无法判断是否真的修改了(ABA问题) ETag ETag If-Match | If-None-Match 能够解决ABA问题,以及能够解决一秒内多次修改的为题
-
-
缓存的使用总结
- 若要兼容HTTP1.0
- 使用Expires,否则直接使用Cache-Control
- 若要处理1秒内的多次修改使用ETag,否则使用Last-Modified
- 对于需要缓存的资源:
- 服务端: 设定 Expires / Cache-Control + ETag/Last-Modified
- 客户端: 携带: If-Modified-Since | If-Match
- 文件标识的采用特殊的形式,如 版本号+md5 ,避免304
HTTP CORS
-
同源的定义: 指的是protocol,port和host都相同,则两个URL同源,也称为协议主机端口元组
- 注意: 协议(http1.0 或者 http1.1等)也需要相同
-
跨域访问:
- 跨域写: 一般是被允许的
- 跨域资源嵌入: 也是被允许的
- 跨域读操作: 则一般不是被允许的
-
相关的头部字段:
- access-control-allow-headers 所允许的头部字段
- access-control-max-age: 表明有效时间内,无需发起预检请求
- access-control-allow-credentials: 为true表示,浏览器如果没有凭证传过来,则服务器不会响应数据
- access-control-allow-origin: 所孕育接受的请求的来源
-
相关的cors字段:
- Origin: 表示来请求来源于哪站
-
其他:
- option是预检请求,检验服务器是否有特殊的要求,如Content-Type,header等信息
-
注意:
- 当浏览器ajax withCrentials设置为true时,如果服务器未携带access-control-allow-credentials,则浏览器依旧无法解析到数据
HTTPS
- 使用对称加密和非对称加密
- Q: 对所有的客户端都是同一种加密算法吗
- A: 不是,不同的客户端使用不同的加密算法,采用随机数的方式来统一加密算法
- Q: 客户端如何获取服务器的公钥
- A: 客户端向服务器发起请求获取
- Q: 若中途被掉包怎么办
- A: 使用数字证书,既不能将服务器端公钥直接传递给客户端,而是第三方机构使用私钥签名之后再发送给客户端,客户端使用第三方机构的公钥验签之后在选择该公钥
- Q: 若第三方机构是违法中间人怎么办
- A: 使用数字签名解决第三方机构合法性问题
- Q: 第三方机构如何合法性校验
- A: 客户端本地验证
- Q: 为什么不采用远程验证
- A: 因为又多了一次交互
- Q: 本地如何验证:
- A: 浏览器和OS,自己维护一个权威的第三方机构列表
- Q: 为什么不采用远程验证
- A: 客户端本地验证
- Q: 若中途被掉包怎么办
- A: 客户端向服务器发起请求获取
传输层
TCP和UDP
-
TCP基于连接而UDP基于无连接
-
TCP面向字节流和UDP 面向数据报
-
TCP的传输是可靠的,而UDP的传输不可靠
-
TCP是点对点的而UDP支持点对多 (UDP广播)
-
Q: 为什么说TCP是面向字节流的,而UDP是面向数据报的
- A: 因为在udp中无论字节数据多长,都是一口气发送的,任由IP分片,但是在TCP中存在流量控制(滑动窗口机制,以及拥塞控制),使得在TCP层就会将数据拆分以合适的长度发送,并且在nagle算法下,当数据太少的时候,会累积到一个MSS的长度再发送,因此可以认为是一连串的无结构的字节流
TCP
-
TCP首部: 固定20字节
- 第一部分:
- 源目端口 (各16bit)
- 序号:32bit
- TCP连接中传输的字节流中每一个字节都按顺序编号,首部中的序号既报文段中发送的数据的第一个字节序号
- 确认号:32bit
- 4个字节,是期望收到的对方下一个报文的序号
- 2
- 数据偏移量: 4bit
- 保留位: 6bit
- URG
- ACK
- 当ACK=1的时候,确认号(ack)有效,反之无效,建立连接之后,所有发送的报文段都必须把ack置1
- PSH
- RS
- SYN
- 当SYN=1,ACK=0,表明这是一个连接请求的报文
- FIN
- 当FIN=1时,表明次报文的数据发送已经完毕,请求断开连接
- 窗口:16bit
- 3
- 校验和: 16位
- 紧急指针:16位
- 4
- 选项(长度可变)
- padding 填充
- 第一部分:
-
TCP三次握手
- client: 请求与server建立连接: SYN=1,seq=i,client 处于SYNC-SEND状态
- server: 收到client的建立连接请求,回送ack报文,并且也请求建立连接: ACK=1,ack=i+1,SYN=1,seq=j ,server处于SYNC-RECVD状态
- client: 收到server的ack报文,也回复确认连接建立: ACK=1,ack=j+1 双方处于 ESTABLISHED状态
- Q: 为什么建立连接要3次请求而不是2次连接
- A: 网络通信原因,既server 回送 的 ACK和SYNC报文因为网络原因延迟了,触发了RTO超时重传,则server会重新发送一个,这个请求顺利到达client,双方建立连接之后开始业务处理, 若此时业务处理完毕之后,4次挥手之后,之前的ack报文来了,则又会建立连接,这就是无效连接
-
TCP四次挥手
- client: 请求与server断开连接,FIN=1,seq=i,client处于 FIN-WAIT-1状态
- server: 收到client的断开连接请求,回送确认断开连接报文, ACK=1,ack=i+1,server 处于CLOSE_WAIT状态
- client: 收到server的ACK确认报文后,client处于 FIN-WAIT-2状态
- server: 因为tcp是全双工的,server还在发送数据,当server发送完数据后,server也要请求断开连接,FIN=1,seq=j ,server处于 LAST_ACK状态
- client: 收到server的请求断开连接报文后,需要回复ack 确认断开连接报文: ACK=1,ack=j+1,client处于 TIME-WAIT状态
- client: 之后等待2*msl的时间,进入 CLOSE状态
- Q: 为什么TCP是 四次挥手,而不是 三次挥手
- A: 因为TCP是全双工的,一方断开连接,另一方可能还未有数据发送完毕,多出来的一次连接在于,server端发送完数据之后也要请求断开连接,只有当数据发送完毕才可以断开连接
- Q: 为什么需要等待 2*msl的时间,才可以进入closed状态:
- A: msl:
max segment lifetime,最大报文生存周期
,当client发送 ack确认报文后,可能这个ack报文会在网络中丢失,则server端会触发RTO,重新发送FIN报文,client端收到后可以继续发送ack报文,这样就可以是一个循环,2*msl的时间内可以确认这个流程的发生
- A: msl:
TCP可靠性传输
- 涉及到: TCP重传机制,TCP快速重传,TCP的确认应答
超时重传:
- 发送方会为每个包创建一个RTO(Retamission TimeOut 超时重传),超时时间与RTT(Round Trip Time有关),在这个时间段未收到ack确认包,则会触发超时重传,达到一定次数还未收到则会断开连接
快速重传:
- 直接发送该报文,而不需要等待RTO超时 (注:这里还会触发拥塞控制)
SACK
-
SACK(Selective acknowledge):TCP中的额外报头,
作用在于收集汇报收到的数据碎板,使得不需要重复发送一些数据报
, -
Q: TCP为什么认为是可靠性的:
-
涉及到 传输可靠性和数据可靠性
-
传输可靠性
: 涉及到 TCP重传机制和确认应答-
A: 因为TCP能确保数据包到达目的主机
-
接收方收到包之后会回送一个ack确认报文,并且ack为发送包的seq+1,并且tcp的ack机制为: 只可确认接收到的最大的连续报,如发送方滑动窗口机制,发送了 1,2,3,4,5个包,1,2,4,5被接收方接收,但是3却在网络中丢失,则此时返回的ack报文只会为3
-
超时重传:发送方会为每个包创建一个RTO(Retamission TimeOut 超时重传),超时时间与RTT(Round Trip Time有关),在这个时间段未收到ack确认包,则会触发超时重传,达到一定次数还未收到则会断开连接
-
接收方因为seq=3 的包迟迟未收到,采取死等的方式(
不确定
)- 解决方法: 快速重传
- 接收方因为一直没有收到3这个包,会一直回复ack=3 ,则在发送端,当ack一直收到3,叫做duplicate ack 达到3次,则会触发快速重传,
直接发送该报文,而不需要等待RTO超时
(注:这里还会触发拥塞控制)
-
Q: 引申问题,这里seq=3最终被接收方收到之后,4,5因为已经收到了,那发送方可能会发送4,5包吗
-
A: 可能,但是有避免方法, 关键字 SACK
-
SACK(Selective acknowledge):TCP中的额外报头, 作用在于收集汇报收到的数据碎板,如之前,4,5也收到了,则在sack中会有SACK 4-5 ,则当发送方收到这个duplicate ack的时候,发现了sack中的内容,4,5包则不会重复发送
-
-
-
数据可靠性
: 涉及到 checksum
-
TCP性能
- 涉及到: TCP流动窗口,TCP拥塞控制,MTU,MSS
- tcp是动态的,可以动态的勘测网络信息,避免网络拥挤时发送过多的数据包,或者过少的时候发送丁点数据浪费带宽
滑动窗口
- tcp发包如果采取发一包收到一个包之后再发下一个包,未免性能太低,TCP滑动窗口使得数据包可以批量发送
- 原理: 批量发送n个窗口的包给接收端,ack一个则滑动窗口向前推动一个,但是注意,窗口过大会使得接收方无法处理导致丢包,而窗口过小会导致无法充分利用带宽
拥塞控制:
- 用于动态发包,防止网络阻塞时发送过多数据,以及网络开放时浪费带宽
慢启动
-
宗旨:不要一开始就发送大量的数据,探测下网络,逐渐增加拥塞窗口大小,在这期间还会收到接收方的接收窗口(rwnd),此时发送的数据大小为 min(cwnd,rwnd)
-
如: 刚开始 cwnd=1 ,代表可以发送一个MSS大小的数据
- 每收到一个ACK,cwnd++
线性增加
- 每过一个RTT,cwnd^=2
指数增加
- 注意,还有一个ssthresh的概念, ssthresh: 拥塞堵塞的阈值,当cwnd达到这个大小的时候,执行拥塞避免算法
- 每收到一个ACK,cwnd++
拥塞避免
- 当cwnd>=ssthresh的时候,进入拥塞避免算法,cwnd 下降
- 作用:
避免增长过快,导致网络堵塞
- 每收到一个ACK cwnd=cwnd+1/cwnd
- 每过一个RTT时间 cwnd=cwnd+1
拥塞状态
- 触发情况: 丢包(RTO超时 || TCP快速重传)
- RTO超时时的流量控制为
- sshthresh=cwnd/2
- cwnd=1
- 重启慢启动过程
- 快速重传时的流量控制为
- cwnd减半 cwnd=cwnd/2
- sshthresh=cwnd
- 进入快速恢复算法
快速恢复
-
触发条件: 快速重传导致的拥塞状态,
-
理由: :有3个duplicate ack 表明网络并不是那么糟糕,不需要像RTO那般剧烈
-
目的: 快速将duplicate ack的包重传
-
在进入快速恢复算法的时候,处于拥塞状态,cwnd,sshthresh已经变更:
- cwnd=cwnd/2
- sshthres=cwnd
-
快速恢复算法流量控制:
- cwnd=sshthresh+3*MSS (
3代表着有3个MSS收集到了
) - 重传duplicate ack的包
- 如果再收集到 duplicate ack,则 cwnd=cwnd+1
- 如果收到了新的ACK,则cwnd=sshthresh,进入拥塞避免算法
- cwnd=sshthresh+3*MSS (
-
Q: TCP是如何实现动态勘测网络情况,从而动态发包的
-
涉及到 慢开始,拥塞控制(ssthresh),拥塞窗口(cwnd),接收窗口(rwnd)
-
滑动窗口:tcp发包如果采取发一包收到一个包之后再发下一个包,未免性能太低,TCP滑动窗口使得数据包可以批量发送
- 原理: 批量发送n个窗口的包给接收端,ack一个则滑动窗口向前推动一个,但是注意,窗口过大会使得接收方无法处理导致丢包,而窗口过小会导致无法充分利用带宽
-
拥塞控制:
-
tcp刚开始发送包的时候,是一个慢启动的过程,发送方维护一个变量拥塞窗口cwnd,该变量取决于网络的拥塞程度
-
慢启动: 不要一开始就发送大量的数据,探测下网络,逐渐增加拥塞窗口大小,在这期间还会收到接收方的接收窗口(rwnd),此时发送的数据大小为 min(cwnd,rwnd)
- 如: 刚开始 cwnd=1 ,代表可以发送一个MSS大小的数据
- 每收到一个ACK,cwnd++
线性增加
- 每过一个RTT,cwnd^=2
指数增加
- 注意,还有一个ssthresh的概念, ssthresh: 拥塞堵塞的阈值,当cwnd达到这个大小的时候,执行拥塞避免算法
- 每收到一个ACK,cwnd++
- 如: 刚开始 cwnd=1 ,代表可以发送一个MSS大小的数据
-
拥塞避免:当cwnd>=ssthresh的时候,进入拥塞避免算法,cwnd 下降
- 作用:
避免增长过快,导致网络堵塞
- 每收到一个ACK cwnd=cwnd+1/cwnd
- 每过一个RTT时间 cwnd=cwnd+1
- 作用:
-
拥塞状态: 发生丢包的情况就代表网络糟糕,进入拥塞状态
- RTO超时时的流量控制为
- sshthresh=cwnd/2
- cwnd=1
- 重启慢启动过程
- 快速重传时的流量控制为
- cwnd减半 cwnd=cwnd/2
- sshthresh=cwnd
- 进入快速恢复算法
- RTO超时时的流量控制为
-
快速恢复: 主旨:有3个duplicate ack 表明网络并不是那么糟糕,不需要像RTO那般剧烈
- 目的: 快速将duplicate ack的包重传
- 在进入快速恢复算法的时候,处于拥塞状态,cwnd,sshthresh已经变更:
- cwnd=cwnd/2
- sshthres=cwnd
- 快速恢复算法流量控制:
- cwnd=sshthresh+3*MSS (
3代表着有3个MSS收集到了
) - 重传duplicate ack的包
- 如果再收集到 duplicate ack,则 cwnd=cwnd+1
- 如果收到了新的ACK,则cwnd=sshthresh,进入拥塞避免算法
- cwnd=sshthresh+3*MSS (
-
-
-
Q: MTU 是什么
- A: MTU是
最大传输单元
,在基于以太网协议中,默认为1500,不同的链路层协议有不同的MTU大小,1500包含了IP20字节,所以给TCP/UDP及其之上的数据大小为1480字节,当 超过这个值就会发生IP分片(前提是IP中的头部 DF=0 代表可以分片
)
- A: MTU是
-
Q: 什么是MSS
- A: Max Segment Size: 最大报文大小,由TCP三次握手建立连接时候可以得知
- Q: MSS和MTU的关系
- A: MSS=MTU-IP首部(20)-TCP首部(20) ,其中 MTU为连接双方的最小MTU
-
Q: 什么时候进入拥塞避免
- A: 当 cwnd>=sshthresh 的时候,cwnd呈线性增长,防止增长过快导致网络阻塞
-
Q: 什么时候进入拥塞状态
- A: 当发生了丢包 (既RTO超时或者是TCP快速重传)
问题
-
204状态码,No Content的具体作用
-
cache-control 中
- no-cache和 max-age=0 的区别
- 以及no-cache 禁用缓存,是否会真的禁用缓存?
-
Q: 什么是实体首部字段
- A: 既资源的字段
-
Q: pragma,cache-control,expires的优先级
-
Q: no-cache和no-store的区别
-
Q: 资源A ,如何强制从服务器获取最新的资源:
- Cache-Controle:max-age=0 +If-Modified-Since 强制请求浏览器判断是否过期,
- 是则返回304,缓存中的数据是最新的数据
- 否: 返回200 ,不是从缓存中获取数据
- Cache-Controle:max-age=0 +If-Modified-Since 强制请求浏览器判断是否过期,
-
Q: 为什么要避免304,以及如何避免304
- A: 304 代表着需要向服务器发起请求,避免304也就避免了请求,减少IO 网络通信
- 如何避免304:
- 既使得浏览器从缓存中获取值,既状态码为 200 (from cache)
- 服务端返回的时候,设定Cache-Control + Last-Modified: 并且时间设置合理,使得获取资源的时候发现本地资源并没有过期,直接从缓存中拿
- 既使得浏览器从缓存中获取值,既状态码为 200 (from cache)