十一、HTTP协议(请求报文和响应报文)
11.1 请求报文
HTTP请求报文主要包括:请求行、请求头部以及请求的数据(实体)。
1.请求行:方法字段、URI字段和协议版本
方法字段:GET(请求获取内容)、POST(提交表单)、HEAD(请求资源响应消息报头)、PUT(传输文件)、DELETE(请求删除URI指向的资源)、OPTIONS(查询针对请求URI指定的资源支持的方法)、TRACE(追踪请求经过路径)、CONNECT(要求用隧道协议连接代理)
2.请求头部
常见标头有:Connection标头(连接管理)、Host标头(指定请求资源的主机)、Range标头(请求实体的字节范围)、User-Agent标头(包含发出请求的用户信息)、Accept标头(首选的媒体类型)、Accept-Language(首选的自然语言)
3.HTTP请求的body主要用于提交表单场景。实际上,http请求的bodt是比较自由的,只要浏览器端发送的body服务端认可就可以了。一些常见的body格式是:
application/json
application/x-www-form-urlencoded
multipart/form-data
text/xml
使用html的form标签提交产生的html请求,默认会产生 application/x-www-form-urlencoded 的数据格式,当有文件上传时,则会使用multipart/form-data。
11.2 响应报文
HTTP响应报文分为三个部分:状态行、首部行和实体;
1.状态行:版本、状态码和原因语句
状态码:
(1)1xx:这一类型的状态码,代表请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束;
(2)2xx:这一类型的状态码,代表请求已成功被服务器接收、理解并接受;
(3)3xx:这类状态码代表需要客户端采取进一步的操作才能完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的Location域中指明。
(4)4xx:这类状态码代表客户端类的错误;
(5)5xx:服务器类的错误。
200---OK/请求已经正常处理完毕
204---请求处理成功,但没有资源返回
206---表示客户端进行了范围请求,而服务器成功执行了这部分的GET请求
301---/请求永久重定向 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。
302---/请求临时重定向 由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。
303---表示由于请求对应的资源存在着另一个URI,应使用GET方法定向获取请求的资源
304---/表示客户端发送附带条件的请求(指采用GET方法的请求报文中包含If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since中任一首部)时,服务端允许请求访问资源,但未满足条件的情况
307---临时重定向,与302含义相同,但是307会遵照浏览器标准,不会从POST变成GET
400---/客户端请求存在语法错误
401---/当前请求需要用户验证。
403---/服务器已经理解请求,但是拒绝执行它。与401响应不同的是,身份验证并不能提供任何帮助
404---/请求失败,请求所希望得到的资源未被在服务器上发现。
405---/请求行中指定的请求方法不能被用于请求相应的资源。
500---/服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。
501---/服务器不支持当前请求所需要的某个功能。当服务器无法识别请求的方法,并且无法支持其对任何资源的请求。
503---/由于临时的服务器维护或者过载,服务器当前无法处理请求。
505---/服务器不支持,或者拒绝支持在请求中使用的 HTTP 版本。
2.响应首部
Date(响应的时间)、Via(报文经过的中间节点)、Last-Modified(上一次修改时间)、Etag(与此实体相关的实体标记)、Connection(连接状态)、Accept-Ranges(服务器可接收的范围类型)、Content-Type(资源类型)
十二、Cookie和Session
12.1 Cookie 大小4KB
Cookie的工作机制是用户识别及状态管理。
1.Set-Cookie
该首部字段用来告知客户端有关Cookie的各种信息
2.Cookie
该首部字段用来告知服务器,当客户端想获得HTTP状态管理支持时,就会在请求中包含从服务器接收到的Cookie。
3.HTTP是无状态的协议,即HTTP协议自身不对请求和响应之间的通信状态进行保存。但为了实现期望的保持状态功能,于是引入了Cookie技术。
Cookie会根据从服务端发送的响应报文内的一个叫做Set-Cookie的首部字段信息,通知客户端保存Cookie。当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入Cookie值发送出去。
4.expires/Max-Age 字段为此cookie超时时间。若设置其值为一个时间,那么当到达此时间后,此cookie失效。不设置的话默认值是Session,意思是cookie会和session一起失效。当浏览器关闭(不是浏览器标签页,而是整个浏览器) 后,此cookie失效。
12.2 Session
Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
1.后端怎么存储session?
在服务器内存中开辟一块地址空间,专门存放每个客户端的私有数据,每个客户端根据cookie中保持的sessionId,可以获取到session数据。
12.3 Cookie与Session区别
1)、Cookie和Session都是会话技术,Cookie是运行在客户端,Session是运行在服务器端。
2)、Cookie有大小限制4K以及浏览器在存cookie的个数也有限制,Session是没有大小限制和服务器的内存大小有关。
3)、Cookie有安全隐患,通过拦截或本地文件找得到你的cookie后可以进行攻击。
4)、Session是保存在服务器端上会存在一段时间才会消失,如果session过多会增加服务器的压力。
session用于保存重要的信息,cookie用于保存不重要的用户信息
十三、登陆验证
由于HTTP是无状态的,一次请求结束,连接断开,下次服务器再收到请求,它就不知道这个请求是哪个用户发过来的。所以需要状态管理,以便服务端能够准确的知道http请求是哪个用户发起的,从而判断用户是否有权限继续这个请求。这个过程就是常说的会话管理。
13.1 同域登陆
如果前端,后台API部署在同域下,不存在跨域的情况,登录方式相对简单
1.基于Session登录
服务器端使用Session技术,浏览器端使用Cookie技术。
session在一开始并不具备会话管理的作用。它只有在用户登录认证成功之后,并且往sesssion对象里面放入了用户登录成功的凭证,才能用来管理会话。管理会话的逻辑也很简单,只要拿到用户的session对象,看它里面有没有登录成功的凭证,就能判断这个用户是否已经登录。当用户主动退出的时候,会把它的session对象里的登录凭证清掉。所以在用户登录前或退出后或者session对象失效时,肯定都是拿不到需要的登录凭证的。
其实上述可以解释为:
登录时带着自身的用户名和密码,将用户登录成功的凭证信息存储在Session中,并生成Cookie,并通过Set-Cookie在响应中返回;第二次登陆时,在请求中添加Cookie后发送,服务端检查Cookie,然后进行响应。
2.基于Token登录
(1).用户在浏览器中输入用户和密码,后台服务器通过加密或者其他逻辑,生成一个Token。
(2).前端获取到Token,存储到cookie或者localStorage中,在接下来的请求中,将token通过url参数或者HTTP Header头部传入到服务器
(3).服务器获取token值,通过查找数据库判断当前token是否有效
13.2 跨域登陆
由于浏览器同源策略,凡是发送请求的url的协议、域名和端口号三者之间任意一个与当前页面不同则视为跨域
1.解决同源策略
基于Session和Token登录都要解决
通过在服务端设置Header,设置Access-Control-Allow-Origin
如果要发送Cookie,Access-Control-Allow-Origin就不能设置星号,必须指定明确的、与请求网页一致的域名。
2.解决请求带上Cookie信息
CORS默认不发送Cookie和HTTP认证信息,一方面服务器制定Access-Control-Allow-Credentials:true 另一方面开发者必须在Ajax请求中添加withCredentials属性。
十四、HTTP1.0、HTTP1.1、HTTP2.0
14.1 HTTP的基本优化
影响HTTP网络请求的因素主要有两个:带宽和延迟
1.带宽
已经得到极大提升
2.延迟
(1)浏览器阻塞:浏览器对于同一个域名,同时只能有6个连接(不同浏览器不同),超过浏览器最大连接数限制,后续请求就会被阻塞。
(2)DNS查询:浏览器需要知道目标服务器的IP才能建立连接,通常可以利用DNS缓存结果来达到减少这个时间的目的。
(3)建立连接:HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文,达到真正的建立连接,但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。
14.2 HTTP1.0和HTTP1.1的一些区别
1.缓存处理 在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Etag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
2.带宽优化及网络连接的使用 HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
3.错误通知的管理
在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
4.Host头处理
在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
5.长连接 HTTP 1.1支持长连接(PersistentConnection)和管线化处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection:keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
14.3 扩展:HTTP1.1的几个特点
1.持久连接 每个TCP连接开始都有三次握手,要经历一次客户端与服务器间完整的往返,而开启了持久化连接就能不必每次都要握手。
持久化连接Connection:keep-alive
2.HTTP管道
持久HTTP多次请求必须严格满足先进先出(FIFO)的队列顺序:发送请求,等待响应完成,再发送客户端队列中的下一个请求。
HTTP管道可以让我们把FIFO队列从客户端(请求队列)迁移到服务器(响应队列)。
但HTTP 1.x不允许一个连接上的多个响应数据交错到达(多路复用),因而一个响应必须完全返回后,下一个响应才会开始传输。
14.4 HTTP的瓶颈
一条连接上只可发送一个请求;
请求只能从客户端开始。客户端不可以接收除响应以外的指令;
请求/响应首部未经压缩就发送。首部信息越多延迟越大;
发送冗长的首部。每次互相发送相同的首部造成的浪费较多;
可任意选择数据压缩格式。非强制压缩发送;
14.5 HTTP2.0
HTTP2.0是在SPDY基础上形成的下一代互联网通信协议。HTTP/2的目的是通过支持请求和响应的多路复用来减少延迟,通过压缩HTTP首部字段将协议开销降低,同时增加请求优先级和服务端推送的支持。
一、HTTP2.0相对于HTTP1.X的新特性
1.二进制分帧层
二进制分帧层是HTTP2.0性能增强的核心
HTTP 1.x在应用层以纯文本的形式进行通信,而HTTP 2.0将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码。这样,客户端和服务端都需要引入新的二进制编码和解码的机制
(1)帧
HTTP2.0通信的最小单位,包括帧首部、流标识符、优先值和帧净荷等。
其中,帧类型又可以分为
:
DATA:用于传输HTTP消息体;
HEADERS:用于传输首部字段;
SETTINGS:用于约定客户端和服务端的配置数据。比如设置初识的双向流量控制窗口大小;
WINDOWUPDATE:用于调整个别流或个别连接的流量
PRIORITY:用于指定或重新指定引用资源的优先级。
RST_STREAM:用于通知流的非正常终止。
PUSH PROMISE:服务端推送许可。
PING:用于计算往返时间,执行“ 活性” 检活。
GOAWAY:用于通知对端停止在当前连接中创建流。
(2)消息
消息是指逻辑上的HTTP消息(请求/响应)。一系列数据帧组成了一个完整的消息。
(3)流
流是连接中的一个虚拟信道,可以承载双向消息传输。每个流有唯一整数标识符。为了防止两端流ID冲突,客户端发起的流具有奇数ID,服务端发起的流具有偶数ID。
所有HTTP2.0通信都在一个TCP连接上完成,这个连接可以承载任意数量的双向数据流Stream。相应地,每个数据流以消息的形式发送,而消息由一个或多个帧组成,这些帧可以乱序发送,然后根据每个帧首部的流标识符重新组装。
2.多路复用共享连接 HTTP消息被分解为独立的帧,而不破坏消息本身的语义,交错发送出去,最后在另一端根据流ID和首部将它们重新组合起来。
HTTP2.0成功解决了HTTP1.x的队首阻塞问题(TCP层的阻塞仍无法解决),同时减少了TCP连接数对服务器性能有很大提升。
- 可以并行交错地发送请求,请求之间互不影响; 可以并行交错地发送响应,响应之间互不干扰;只使用一个连接即可并行发送多个请求和响应; 消除不必要的延迟,从而减少页面加载的时间;不必再为绕过 HTTP 1.x 限制而多做很多工作;
3.请求优先级 流可以带有一个31bit的优先级:
0:表示最高优先级
2的31次方-1 表示最低优先级。
服务端按优先级返回结果有利于高效利用底层连接,提高用户体验。
4.服务端推送
HTTP2.0增加了服务端推送功能,服务端可以根据客户端的请求,提前返回多个响应,推送额外的资源给客户端。
HTTP 2.0 连接后,客户端与服务器交换SETTINGS 帧,借此可以限定双向并发的流的最大数量。因此,客户端可以限定推送流的数量,或者通过把这个值设置为0 而完全禁用服务器推送。
所有推送的资源都遵守同源策略。换句话说,服务器不能随便将第三方资源推送给客户端,而必须是经过双方确认才行。
PUSH_PROMISE帧是服务端向客户端有意推送资源的信号。
如果客户端不需要服务端Push,可在SETTINGS帧中设定服务端流的值为0,禁用此功能
PUSH_PROMISE帧中只包含预推送资源的首部。如果客户端对PUSH_PROMISE帧没有意见,服务端在PUSH_PROMISE帧后发送响应的DATA帧开始推送资源。如果客户端已经缓存该资源,不需要再推送,可以选择拒绝PUSH_PROMISE帧。
PUSH_PROMISE必须遵循请求-响应原则,只能借着对请求的响应推送资源。
几点限制:
服务器必须遵循请求- 响应的循环,只能借着对请求的响应推送资源
PUSH_PROMISE 帧必须在返回响应之前发送,以免客户端出现竞态条件。
5.首部压缩
HTTP1.x每一次通信(请求/响应)都会携带首部信息用于描述资源属性。HTTP2.0在客户端和服务端之间使用“首部表”来跟踪和存储之前发送的键值对.首部表在连接过程中始终存在,新增的键值对会更新到表尾,因此,不需要每次通信都需要再携带首部。
HTTP2.0使用了首部压缩技术,可让报头更紧凑、更快速传输。HTTP 2.0关注的是首部压缩,而我们常用的gzip等是报文内容(body)的压缩。
二、HTTP2.0的完整通信过程
在两端使用HTTP2.0通信之前,必然存在协议协商的过程。
1.基于ALPN的协商过程
HTTPS 协商过程中有一个环节会使用ALPN(应用层协议协商)。减少网络延迟是HTTP 2.0 的关键条件,因此在建立HTTPS 连接时一定会用到ALPN协商。
支持HTTP 2.0的浏览器可以在TLS会话层自发完成和服务端的协议协商以确定是否使用HTTP 2.0通信。其原理是TLS 1.2中引入了扩展字段,以允许协议的扩展,其中ALPN协议(Application Layer Protocol Negotiation, 应用层协议协商, 前身是NPN)用于客户端和服务端的协议协商过程。
2.基于HTTP的协商过程
客户端使用HTTP也可以开启HTTP 2.0通信。只不过因为HTTP 1. 0和HTTP 2. 0都使用同一个 端口(80), 又没有服务器是否支持HTTP 2. 0的其他任何 信息,此时 客户端只能使用HTTP Upgrade机制(OkHttp, nghttp2等组件均可实现,也可以自己编码完成)通过协调确定适当的协议
3.完整通信过程 (1)TCP连接建立
(2)TLS握手和HTTP2.0通信过程
1)TLS握手
2)客户端向服务端发送SETTINGS帧,约定配置
3)流量控制
4)客户端向服务端发送HEADERS帧
5)服务端返回配置
6)DATA帧传输数据
三、发起新流
在发送应用数据之前,必须创建一个新流并随之发送相应的元数据,比如流优先级、HTTP 首部等;
客户端通过发送HEADERS帧来发起新流;
服务器通过发送 PUSH_PROMISE 帧来发起推送流。
四、发送应用数据
创建新流并发送HTTP 首部之后,接下来就是利用DATA 帧。应用数据可以分为多个DATA 帧,最后一帧要翻转帧首部的END_STREAM 字段
HTTP 2.0 标准要求DATA 帧不能超过2的14次方-1(16383)字节。长度超过这个阀值的数据,就得分帧发送。
五、去掉对HTTP1.X的优化
每个来源使用一个连接,HTTP 2.0 通过将一个TCP 连接的吞吐量最大化来提升性能。
去掉不必要的文件合并和图片拼接:HTTP 2.0,很多小资源都可以并行发送
利用服务器推送:之前针对HTTP 1.x 而嵌入的大多数资源,都可以而且应该通过服务器推送来交付。
十五、HTTPS
15.1 HTTP的缺点
1.通信使用明文(不加密),内容可能会被窃听;
TCP/IP是可能被窃听的网络:按TCP/IP协议族的工作机制,通信内容在所有线路上都有可能遭到窥视。
加密处理防止被窃听,加密的对象如下:
(1)通信的加密 通过和SSL(Secure Socket Layer,安全套接层)或TLS(Transport Layer Security,安全层传输协议)的组合使用,加密HTTP的通信内容。用SSL建立安全通信线路之后,就可以在这条线路上进行HTTP通信了。与SSL组合使用的HTTP称为HTTPS。
这种方式将整个通信线路加密
(2)内容的加密 由于HTTP协议中没有加密机制,那么就对HTTP协议传输的内容本身加密。
为了做到有效的内容加密,前提是要求客户端和服务器同时具备加密和解密机制。
该方式不同于将整个通信线路加密处理,内容仍有被篡改的风险。
2.不验证通信方的身份,因此有可能遭遇伪装;
(1)任何人都可发起请求
HTTP协议不论是谁发送过来的请求都会返回响应,因此不确认通信方,会存在以下隐患:
无法确定请求发送至目标的Web服务器是否是按真是意图返回响应的那台服务器,有可能是已伪装的Web服务器。
无法确定响应返回到的客户端是否是按照真实意图接收响应的那个客户端,有可能是伪装的客户端。
无法确定正在通信的对方是否具备访问权限,因为某些Web服务器上保存着重要的信息,只想发给特定用户通信的权限。
无法判断请求是来自何方、出自谁手
即使是无意义的请求也会照单全收,无法阻止海量请求下的Dos攻击(Denial of Service,拒绝服务攻击)。
(2)查明对手的证书
SSL不仅提供加密处理,还使用了一种被称为证书的手段,可用于确定通信方。
证书由值得信任的第三方机构颁发,用以证明服务器和客户端是实际存在的。
使用证书,以证明通信方就是意料中的服务器,对使用者个人来讲,也减少了个人信息泄露的危险性。另外,客户端持有证书即可完成个人身份的确认,也可用于对Web网站的认证环节。
3.无法证明报文的完整性,所以有可能已遭遇篡改。
(1)接收到的内容可能有误
在请求或响应送出之后直到对方接收之前的这段时间内,即使请求或响应的内容遭到篡改,也没有办法获悉。
在请求或响应的传输途中,遭攻击者拦截并篡改内容的攻击称为中间人攻击(Man-in-the-Middle attack)。
(2)如何防止篡改
仅靠HTTP确保完整性是非常困难的,便有赖于HTTPS来实现。SSL提供认证和加密处理及摘要功能。
15.2 HTTPS是如何加密数据的
把添加了加密、认证机制、完整性保护的HTTP称为HTTPS
HTTPS 并非是应用层的一种新协议。只是 HTTP 通信接口部分用SSL(Secure Socket Layer)和TLS(Transport Layer Security) 协议代替而已。
TLS的前身是SSL
通常,HTTP直接和TCP通信,当使用SSL时,则演变成先和SSL通信,再由SSL和TCP通信了,简言之,所谓HTTPS其实就是身披SSL协议这层外壳的HTTP
SSL协议使用通信双方的客户证书以及CA根证书,允许客户/服务器应用以一种不能被偷听的方式通信,在通信双方间建立起了一条安全的、可信任的通信通道。
1.加密分为对称加密和非对称加密(也叫公开密钥加密)
(1)对称加密的意思就是,加密数据用的密钥,跟解密数据用的密钥是一样的。
1)对称加密的优点在于加密、解密效率通常比较高。速度快,对称性加密通常在消息发送方需要加密大量数据时使用,算法公开、计算量小、加密速度快、加密效率高。
2)缺点在于,数据发送方、数据接收方需要协商、共享同一把密钥,并确保密钥不泄露给其他人。此外,对于多个有数据交换需求的个体,两两之间需要分配并维护一把密钥,这个带来的成本基本是不可接受的。
(2)非对称加密的意思就是,加密数据用的密钥(公钥),跟解密数据用的密钥(私钥)是不一样的。
公钥就是公开的密钥,谁都可以查到;私钥就是非公开的密钥,一般是由网站的管理员持有。
公钥与私钥的联系:简单的说就是,通过公钥加密的数据,只能通过私钥解开。通过私钥加密的数据,只能通过公钥解开。
2.公开密钥存在问题
问题一:公钥如何获取;
问题二:数据传输仅单向安全(因为私钥加密数据,公钥也能解开,所以只是单向安全)
(1)对于公钥如何获取这个问题
这里涉及两个重要概念:证书、CA(证书颁发机构)
证书:可以暂时把它理解为网站的身份证。这个身份证里包含了很多信息,其中就包含了上面提到的公钥。当访问相应网站时,他就会把证书发给浏览器;
证书来自于CA(证书颁发机构)
(2)证书可能存在的问题:
证书是伪造的:压根不是CA颁发的
证书被篡改过:比如将XX网站的公钥给替换了
数字签名、摘要是证书防伪非常关键的武器。
“摘要”就是对传输的内容,通过hash算法计算出一段固定长度的串。然后,在通过CA的私钥对这段摘要进行加密,加密后得到的结果就是“数字签名”。
明文 --> hash运算 --> 摘要 --> 私钥加密 --> 数字签名
数字签名只有CA的公钥才能够解密。
证书格式,需要关注的有几个点:
证书包含了颁发证书的机构的名字 -- CA
证书内容本身的数字签名(用CA私钥加密)
证书持有者的公钥
证书签名用到的hash算法
其中CA本身有自己的证书,称为根证书。
1)对于完全伪造的证书
这种情况对证书进行检查
证书颁发的机构是伪造的:浏览器不认识,直接认为是危险证书
证书颁发的机构是确实存在的,于是根据CA名,找到对应内置的CA根证书、CA的公钥。用CA的公钥,对伪造的证书的摘要进行解密,发现解不了。认为是危险证书
2)篡改过的证书
检查证书,根据CA名,找到对应的CA根证书,以及CA的公钥。
用CA的公钥,对证书的数字签名进行解密,得到对应的证书摘要AA
根据证书签名使用的hash算法,计算出当前证书的摘要BB
对比AA跟BB,发现不一致--> 判定是危险证书
15.3 HTTPS流程
1.客户端发起HTTPS请求
2.服务端响应,下发证书(公开密钥证书)
3.客户端检查证书,如果证书没问题,那么就生成一个随机值,然后用证书(公钥)对该随机值进行加密。
4.将经过公钥加密的随机值发送到服务端(非对称加密),以后客户端和服务器的通信就可以通过这个随机值进行加密解密了。
5.服务端用私钥解密后,得到了客户端传过来的随机值,然后把内容通过该值进行对称加密。
6.后期的数据传输都是基于该随机值进行加密解密。
15.4 对于公钥获取这个问题
涉及到证书和CA(证书颁发机构)
证书可能存在的问题:1.证书是伪造的,压根不是CA颁发的;
2.证书被篡改过
数字签名和摘要是证书防伪非常关键的武器
明文--->hash算法--->摘要---->私钥加密----->数字签名
数字签名只有CA的公钥才能够解密
CA证书本身有自己的证书,称为根证书。
(1)对于完全伪造的证书
这种情况对证书进行检查
证书颁发的机构是伪造的:浏览器不认识,直接认为是危险证书
证书颁发的机构是确实存在的,于是根据CA名,找到对应内置的CA根证书、CA的公钥。用CA的公钥,对伪造的证书的数字签名进行解密,发现解不了。认为是危险证书
(2)篡改过的证书
检查证书,根据CA名,找到对应的CA根证书,以及CA的公钥。
用CA的公钥,对证书的数字签名进行解密,得到对应的证书摘要AA
根据证书签名使用的hash算法,计算出当前证书的摘要BB
对比AA跟BB,发现不一致--> 判定是危险证书
15.5 客户端证书
HTTPS中还可以使用客户端证书,以客户端证书进行客户端认证,证明服务器正在通信的对方始终是预料之内的客户端。想获取证书时,用户得自行安装客户端证书。
现状是,安全性极高的认证机构可颁发客户端证书但仅用于特殊用途的业务,比如网上银行等。
15.6 HTTPS问题
1.与纯文本相比,加密通信会消耗更多的CPU及内存资源
由于HTTPS还需要做服务器、客户端双方加密及解密处理,因此会消耗CPU和内存等硬件资源。
和HTTP通信相比,SSL通信部分消耗网络资源,而SSL通信部分,由因为要对通信进行处理,所以时间上又延长了。
SSL慢分两种,一种是指通信慢;另一种是指由于大量消耗CPU及内存等资源,导致处理速度变慢。
2.购买证书需要开销。
十六、WebSocket
16.1 WebSocket API
1.WS和WSS WebSocket资源URL采用了自定义模式,ws表示纯文本通信,wss表示使用加密信道通信(TCP+TLS)
WebSocket的主要目的,是在浏览器中的应用与服务器之间提供优化的、双向通信机制。可是,WebSocket的连接协议也可以用于浏览器之外的场景,可以通过非HTTP协商机制交换数据。
2.接收文本和二进制数据
WebSocket通信只涉及消息,应用代码无需担心缓存、解析、重建接收到的数据。比如,服务器发来了一个1MB的净荷,应用的onmessage回掉只会在客户端接收到全部数据时才会被调用。
净荷可以是文本也可以是二进制数据。
浏览器接收到新消息后,如果是文本数据,会自动将其转换成DOMString对象,如果是二进制数据或Blob对象(Blob对象一般代表一个不可变的文件对象或原始数据。如果你不需要修改它或者不需要把它切分成更小的块,这种格式是理想的,若需要处理则选择ArrayBuffer更合适),会直接将其转交给应用。唯一可以多余设置的,就是告诉浏览器把接收到的二进制数据转换成ArrayBuffer而非Blob
➊ 如果接收到二进制数据,将其强制转换成 ArrayBuffer
3.发送文本和二进制数据
客户端就可以随时发送或接收 UTF-8 或二进制消息
这里的send()方法是异步的:提供的数据会在客户端排队,而函数则立即返回。特别是传输大文件的时候,千万别因为返回快,就认为数据已经发送出去了。可以通过bufferedAmount属性来监控浏览器中排队的数据量。ws.bufferedAmount
4.子协议协商
WebSocket协议对每条消息的格式事先不作任何假设:仅用一位标记消息是文本还是为二进制,以便客户端和服务器有效地解码数据,而除此之外的消息内容就是未知的。
此外,与 HTTP 或 XHR 请求不同——它们是通过每次请求和响应的 HTTP 首部来沟通元数据, WebSocket 并没有等价的机制。因此,如果需要沟通关于消息的元数据,客户端和服务器必须达成沟通这一数据的子协议。
WebSocket为此提供了一个简单便捷的子协议协商API。客户端可以在初次连接握手时,告诉服务器自己支持哪种协议:
,从而得知服务器选定的协议。另一方面,服务器如果不支持客户端声明的任何一个协议,则 WebSocket 握手是不完整的,此时会触发 onerror 回调,连接断开。
16.2 WebSocket协议
WebSocket通信协议包含两个高层组件:开放性HTTP握手用于协商连接参数,二进制消息分帧机制用于支持低开销的基于消息的文本和二进制数据传输。
1.二进制分帧层
WebSocket使用了自定义的二进制分帧格式,把每个消息切分成一或多个帧,发送到目的地之后再组装起来,等到接收到完整的消息后再通知接收端。
帧:最小的通信单位,包含可变长度的帧首部和净荷部分
消息:一系列帧
FIN:表示当前帧是不是消息的最后一帧。
操作码(4位):表示被传输帧的类型:文本(1),二进制(2)
掩码位表示净荷是否有掩码(只适用于客户端发送给服务器的消息)。
算下来,服务器发送的每个WebSocket帧会产生2~10字节的分帧开销。而客户端必须发送掩码键,这又会增加4字节,结果就是6~14字节的开销。除此之外,没有其他元素据。
2.WebSocket的多路复用及队首阻塞
WebSocket很容易发生队首阻塞的情况:消息可能会被分成一个或多个帧,但不同消息的帧不能交错发送,因为没有与HTTP2.0分帧机制中“流ID”对等的字段。
WebSocket不支持多路复用,还意味着每个WebSocket连接都需要一个专门的TCP连接。对于HTTP1.x而言,由于浏览器针对每个来源有连接数量限制,因此可能会导致问题。
虽然通过HTTP2.0传输WebSocket帧的官方规范尚未发布,但相对来说容易很多。因为HTTP2.0内置了流的多路复用,只要通过HTTP2.0的分帧机制来封装WebSocket帧,多个WebSokcet连接就可以在一个会话中传输。
3.协议扩展
(1)多路复用扩展
这个扩展可以将WebSocket的逻辑连接独立出来,实现共享底层的TCP连接。
(2)压缩扩展
给WebSocket协议增加了压缩功能。
如前所述,每个 WebSocket 连接都需要一个专门的 TCP 连接,这样效率很低。多路复用扩展解决了这个问题。它使用“信道 ID”扩展每个 WebSocket 帧,从而实现多个虚拟的 WebSocket 信道共享一个 TCP 连接。类似地,基本的 WebSocket 规范没有压缩数据的机制或建议,每个帧中的净荷就是应用提供的净荷。虽然这对优化的二进制数据结构不是问题,但除非应用实现自己的压缩和解压缩逻辑,否则很多情况下都会造成传输载荷过大的问题。实际上,压缩扩展就相当于 HTTP 的传输编码协商。
要使用扩展,客户端必须在第一次的Upgrade握手中通知服务器,服务器必须选择并确认要在商定连接中使用的扩展。
4.HTTP升级协商
在交换数据之前,客户端必须与服务器协商适当的参数以建立连接。
利用HTTP完成握手有几个好处。首先,让WebSocket与现有HTTP基础设施兼容:WebSocket服务器可以运行在80和443端口上,这通常是对客户端唯一开放的端口。其次,让我们可以重用并扩展HTTP的Upgrade流,为其添加自定义的WebSocket
首部,以完成协商。
与浏览器中客户端发起的任何连接一样,WebSocket请求也必须遵守同源策略:浏览器会自动在升级握手请求中追加Origin首部,远程服务器可能使用CORS判断接受或拒绝跨源请求。要完成握手,服务器必须返回一个成功的“Switching Protocols”(切换协议)响应,并确认选择了客户端发送的哪个选项:
如果握手成功,该连接就可以用作双向通信信道交换WebSocket消息。从此以后,客户端与服务器之间不会再发生HTTP通信,一切由WebSocket协议接管。
16.3 WebSocket使用场景及性能
1.请求和响应流
WebSocket是唯一一个能通过同一个TCP连接实现双向通信的机制,客户端和服务器随时可以交换数据。
2.消息开销
应用消息会被拆分为一或多个帧,每个帧会添加2~14字节的开销。而且,由于分帧是按照自定义的二进制格式完成的, UTF-8 和二进制应用数据可以有效地通过相同的机制编码。
(1)SSE会给每个消息添加5个字节,但仅限于UTF-8内容
(2)HTTP 1.x 请求(XHR 及其他常规请求)会携带 500~800 字节的 HTTP 元数据,加上 cookie
(3)HTTP 2.0 压缩 HTTP 元数据,这样可以显著减少开销
3.数据效率及压缩
除非应用通过细致优化自己的二进制净荷实现自己的压缩逻辑,同时也针对文本消息实现自己的压缩逻辑,否则传输数据过程中一定会产生很大的字节开销!
4.自定义应用协议
16.4 图解HTTP上解释
WebSocket技术主要是为了解决Ajax和Comet里XMLHttpRequest附带的缺陷所引起的问题。
WebSocket是建立在HTTP基础上的协议,因此连接的发起方仍然是客户端。
Websocket只需要一次HTTP握手,所以说整个通讯过程是建立在一次连接/状态中,也就避免了HTTP的非状态性,服务端会一直知道你的信息,直到你关闭请求
(1)WebSocket的主要特点
1)推送功能
支持由服务器向客户端推送数据的推送功能。
2)减少通信量
只要建立起WebSocket连接,就希望一直保持连接状态。和HTTP相比,不但每次连接时的总开销减少,而且由于WebSokcet的首部信息很小,通信量也相应减少了;
(2)握手请求
为了实现WebSocket通信,在HTTP连接建立之后,需要完成一次“握手”的步骤。
为了实现WebSocket通信,需要用到HTTP的Upgrade首部字段,告知服务器通信协议发生改变,以达到握手的目的。
Sec-WebSocket-Key:记录握手需要的键值;
Sec-WebSocket-Protocol:记录使用的子协议;
(3)握手响应
对于之前的请求,返回状态码101 Switching Protocols的响应。成功握手确立WebSocket连接之后,通信时不再使用HTTP的数据帧,而采用WebSockte独立的数据帧;
Sec-WebSocket-Accept:该字段值是由握手请求中的Sec-WebSocket-Key的字段值生成的;
16.5 WebSocket优点(对比参照HTTP协议)
https://yq.aliyun.com/articles/633679?spm=a2c4e.11153940.0.0.5e293dd6CNm3ZH (1)支持双向通信,实时性更强;
(2)更好的二进制支持;
(3)较少的控制开销:
连接创建后,ws客户端、服务端进行数据交换时,协议控制的数据包头部较小。在不包含头部的情况下,服务端到客户端的包头只有2~10字节(取决于数据包长度),客户端到服务端的的话,需要加上额外的4字节的掩码。而HTTP协议每次通信都需要携带完整的头部;
(4)支持扩展:
ws协议定义了扩展,用户可以扩展协议,或者实现自定义的子协议(比如支持自定义压缩算法等)。
16.6 如何建立连接
WebSocket复用了HTTP的握手通道。具体指的是,客户端通过HTTP请求与WebSocket服务端协商升级协议。协议升级完成后,后续的数据交换则遵照WebSocket的协议。
1.客户端:申请协议升级
首先,客户端发起协议升级请求。可以看到,采用的是标准的HTTP报文格式,且只支持GET方法 Connection: Upgrade:表示要升级协议
Upgrade: websocket:表示要升级到websocket协议。
Sec-WebSocket-Version: 13:表示websocket的版本。如果服务端不支持该版本,需要返回一个Sec-WebSocket-Versionheader,里面包含服务端支持的版本号。
Sec-WebSocket-Key:与后面服务端响应首部的Sec-WebSocket-Accept是配套的,提供基本的防护,比如恶意的连接,或者无意的连接。
2.服务端:响应协议升级
返回状态码101表示协议切换
16.7 数据帧格式
客户端、服务器数据的交换,离不开数据帧格式的定义。
WebSocket客户端、服务端通信的最小单位是帧,由一个或多个帧组成一条完整的消息。
发送端:将消息切割成多个帧,并发送给服务端;
接收端:接收消息帧,并将关联的帧重新组装成完整的消息。
帧内容见上面二小结
16.8 数据传递
一旦WebSocket客户端、服务端建立连接后,后续的操作都是基于数据帧的传递。WebSocket根据opcode来区分操作的类型。比如0x8表示断开连接,0x0-0x2表示数据交互。
1.数据分片
WebSocket的每条消息可能被切分成多个数据帧。当WebSocket的接收方收到一个数据帧时,会根据FIN的值来判断,是否已经收到消息的最后一个数据帧。
FIN=1表示当前数据帧为消息的最后一个数据帧,此时接收方已经收到完整的消息,可以对消息进行处理。FIN=0,则接收方还需要继续监听接收其余的数据帧。
opcode在数据交换的场景下,表示的是数据的类型。0x01表示文本,0x02表示二进制。而0x00比较特殊,表示延续帧(continuation frame),顾名思义,就是完整消息对应的数据帧还没接收完。
16.9 连接保持+心跳
WebSocket为了保持客户端、服务端的实时双向通信,需要确保客户端、服务端之间的TCP通道保持连接没有断开。
有些场景,客户端、服务端虽然长时间没有数据往来,但仍需要保持连接,这个时候可以采用心跳来实现:
发送方->接收方:ping
接收方->发送方:pong
ping、pong的操作,对应的是WebSocket的两个控制帧,opcode分别是0x9、0xA
例如:ws.ping('', false, true);
16.10 Sec-WebSocket-Key/Accept的作用
Sec-WebSocket-Key/Sec-WebSocket-Accept在主要作用在于提供基础的防护,减少恶意连接、意外连接。
16.11 数据掩码的作用
WebSocket协议中,数据掩码的作用是增强协议的安全性。但数据掩码并不是为了保护数据本身(因为算法本身是公开的,运算也不复杂),而是为了防止早期版本的协议中存在的代理缓存污染攻击等问题。
十七、状态码301和302的区别
(1)什么是301重定向?
301重定向/跳转一般,表示本网页永久性转移到另一个地址。
301是永久性转移(Permanently Moved),SEO(搜索引擎优化)常用的招式,会把旧页面的PR(永久居留)等信息转移到新页面;
(2)什么是302重定向?
302重定向表示临时性转移(Temporarily Moved),当一个网页URL需要短期变化时使用。
(3)301重定向与302重定向的区别
301重定向是永久的重定向,搜索引擎在抓取新内容的同时也将旧的网址替换为重定向之后的网址。
302重定向是临时的重定向,搜索引擎会抓取新的内容而保留旧的网址。因为服务器返回302代码,搜索引擎认为新的网址只是暂时的。
十八、强缓存引起问题的解决方案(如何更新网站资源)
存在问题:发布时资源更新问题,更新了资源,但是用户每次请求时依然从缓存中获取原来的资源,除非用户清除或者强刷新,否则看不到最新的效果。
1、利用304定向重定向,让浏览器本地缓存即协商缓存。
缺点:协商缓存还是需要和浏览器通信一次。
2、强制浏览器使用本地缓存,不和服务器通信。
缺点:无法更新缓存。
3、通过更新页面中引用的资源路径,让浏览器主动放弃缓存,加载新资源。例如在文件名称后面增加一个版本号,下次上线时更改版本号。
缺点:当有多个静态缓存文件,只有一个文件更改时,却需要更新所有文件。
采用数据摘要算法
想要解决这个问题:考虑到让url的修改与文件内容相关联即只有文件内容变化时,才会导致相应的url的变更,从而实现文件级别的精确缓存控制。
为了进一步提升网站性能,会把静态资源和动态网页分集群部署,静态资源会被部署到CDN节点上,网页中引用的资源也会变成对应的部署路径。当我要更新静态资源的时候,同时也会更新html中的引用。若这次发布,同时改了页面结构和样式,也更新了静态资源对应的url地址,现在要发布代码上线,咱们是先上线页面,还是先上线静态资源?
先部署页面,再部署资源:在二者部署的时间间隔内,如果有用户访问页面,就会在新的页面结构中加载旧的资源,并且把这个旧版本的资源当做新版本缓存起来,其结果就是:用户访问到了一个样式错乱的页面,除非手动刷新,否则在资源缓存过期之前,页面会一直执行错误。
先部署资源,再部署页面:在部署时间间隔之内,有旧版本资源本地缓存的用户访问网站,由于请求的页面是旧版本的,资源引用没有改变,浏览器将直接使用本地缓存,这种情况下页面展现正常;但没有本地缓存或者缓存过期的用户访问网站,就会出现旧版本页面加载新版本资源的情况,导致页面执行错误,但当页面完成部署,这部分用户再次访问页面又会恢复正常了。
上述先部署谁都有问题,这是因为采用的是覆盖式发布,用 待发布资源 覆盖 已发布资源,就有这种问题。解决它也好办,就是实现 非覆盖式发布。
大公司的静态资源优化方案:
1.配置超长时间的本地缓存 —— 节省带宽,提高性能
2.采用内容摘要作为缓存更新依据 —— 精确的缓存控制
3.静态资源CDN部署 —— 优化网络请求
4.更新资源发布路径实现非覆盖式发布 —— 平滑升级
十九、滑动窗口原理
19.1 TCP滑动窗口(发送窗口和接收窗口)
TCP滑动窗口主要有两个作用,一是提供TCP的可靠性,二是提供TCP的流控特性(TCP的滑动窗口是动态的)。同时滑动窗口机制还体现了TCP面向字节流的设计思路。
TCP的Window是一个16bit位字段,它代表的是窗口的字节容量,也就是TCP的标准窗口最大为2^16 - 1 = 65535个字节。
1.对于TCP会话的发送方,任何时候在其发送缓存内的数据都可以分为4类,“已经发送并得到对端ACK的”,“已经发送但还未收到对端ACK的”,“未发送但对端允许发送的”,“未发送且对端不允许发送”。“已经发送但还未收到对端ACK的”和“未发送但对端允许发送的”这两部分数据称之为发送窗口(中间两部分)。
当收到接收方新的ACK对于发送窗口中后续字节的确认是,窗口滑动,滑动原理如下图。
当收到ACK=36时窗口滑动
2.对于TCP的接收方,在某一时刻在它的接收缓存内存有3种。“已接收”,“未接收准备接收”,“未接收并未准备接收。其中“未接收准备接收”称之为接收窗口。
3.发送窗口和接收窗口关系
TCP是双工的协议,会话的双方都可以同时接收、发送数据。TCP会话的双方都各自维护一个”发送窗口“和一个”接收窗口“。其中各自的”接收窗口“大小取决于应用、系统、硬件的限制(TCP传输速率不能大于应用的数据处理速率)。各种的”发送窗口“则要求取决于对端通告的”接收窗口“,要求相同。
4.滑动窗口实现面向流的可靠性
最基本的传输可靠性来源于”确认重传“机制。
TCP的滑动窗口的可靠性也是建立在”确认重传“基础上的。
发送窗口只有收到对端对于本段发送窗口内字节的ACK确认,才会移动发送窗口的左边界。
接收窗口只有在前面所有的段都确认的情况下才会移动左边界。当在前面还有字节未接收但收到后面字节的情况下,窗口不会移动,并不对后续字节确认。以此确保对端会对这些数据重传。
19.2 TCP协议上的网络协议分类
目前建立在TCP协议上的网络协议特别多,有telnet,ssh,有ftp,有http等等。这些协议又可以根据数据吞吐量来大致分成两大类:
(1)交互数据类型,例如telnet,ssh,这种类型的协议在大多数情况下只是做小流量的数据交换,比如说按一下键盘,回显一些文字等等。
(2)数据成块类型,例如ftp,这种类型的协议要求TCP能尽量的运载数据,把数据的吞吐量做到最大,并尽可能的提高效率。
19.3 滑动窗口协议相关术语
滑动窗口本质上是描述接受方的TCP数据报缓冲区大小的数据,发送方根据这个数据来计算自己最多能发送多长的数据。如果发送发收到接收方的窗口大小为0的TCP数据报,那么发送方将停止发送数据,等到接收方发送窗口大小不为0的数据报的到来。
关于滑动窗口协议介绍了三个术语,分别是:
窗口合拢:当窗口从左边向右边靠近的时候,这种现象发生在数据被发送和确认的时候。
窗口张开:当窗口的右边沿向右边移动的时候,这种现象发生在接受端处理了数据以后。
窗口收缩:当窗口的右边沿向左边移动的时候,这种现象不常发生
19.4 举一个例子来说明一下滑动窗口的原理
TCP并不是每一个报文段都会回复ACK的,可能会对两个报文段发送一个ACK,也可能会对多个报文段发送1个ACK【累计ACK】,比如说发送方有1/2/3 3个报文段,先发送了2,3 两个报文段,但是接收方期望收到1报文段,这个时候2,3报文段就只能放在缓存中等待报文1的空洞被填上,如果报文1,一直不来,报文2/3也将被丢弃,如果报文1来了,那么会发送一个ACK对这3个报文进行一次确认。
举一个例子来说明一下滑动窗口的原理:
1. 假设32~45 这些数据,是上层Application发送给TCP的,TCP将其分成四个Segment来发往internet
2. seg1 32~34 seg3 35~36 seg3 37~41 seg4 42~45 这四个片段,依次发送出去,此时假设接收端之接收到了seg1 seg2 seg4
3. 此时接收端的行为是回复一个ACK包说明已经接收到了32~36的数据,并将seg4进行缓存(保证顺序,产生一个保存seg3 的hole)
4. 发送端收到ACK之后,就会将32~36的数据包从发送并没有确认切到发送已经确认,提出窗口,这个时候窗口向右移动
5. 假设接收端通告的Window Size仍然不变,此时窗口右移,产生一些新的空位,这些是接收端允许发送的范畴
6. 对于丢失的seg3,如果超过一定时间,TCP就会重新传送(重传机制),重传成功会seg3 seg4一块被确认,不成功,seg4也将被丢弃
就是不断重复着上述的过程,随着窗口不断滑动,将真个数据流发送到接收端,实际上接收端的Window Size通告也是会变化的,接收端根据这个值来确定何时及发送多少数据,从对数据流进行流控。原理图如下图所示:
19.5 滑动窗口动态调整
主要是根据接收端的接收情况,动态去调整Window Size,然后来控制发送端的数据流量
客户端不断快速发送数据,服务器接收相对较慢,看下实验的结果
a. 包175,发送ACK携带WIN = 384,告知客户端,现在只能接收384个字节
b. 包176,客户端果真只发送了384个字节,Wireshark也比较智能,也宣告TCP Window Full
c. 包177,服务器回复一个ACK,并通告窗口为0,说明接收方已经收到所有数据,并保存到缓冲区,但是这个时候应用程序并没有接收这些数据,导致缓冲区没有更多的空间,故通告窗口为0, 这也就是所谓的零窗口,零窗口期间,发送方停止发送数据
d. 客户端察觉到窗口为0,则不再发送数据给接收方
e. 包178,接收方发送一个窗口通告,告知发送方已经有接收数据的能力了,可以发送数据包了
f. 包179,收到窗口通告之后,就发送缓冲区内的数据了.
总结一点,就是接收端可以根据自己的状况通告窗口大小,从而控制发送端的接收,进行流量控制
二十、Chrome中的from memory cache与from disk cache
1. 在浏览器开发者工具的Network的Size列会出现的三种情况
- from memory cache
- from disk cache
- 资源本身大小(比如:13.6K)
2. 三级缓存原理
先查找内存,如果内存中存在,从内存中加载;
如果内存中未查找到,选择硬盘获取,如果硬盘中有,从硬盘中加载;
如果硬盘中未查找到,那就进行网络请求;
加载到的资源缓存到硬盘和内存;
3. HTTP状态码及区别
- 200 form memory cache
不访问服务器,一般已经加载过该资源且缓存在了内存当中,直接从内存中读取缓存。浏览器关闭后,数据将不存在(资源被释放掉了),再次打开相同的页面时,不会出现from memory cache。
- 200 from disk cache
不访问服务器,已经在之前的某个时间加载过该资源,直接从硬盘中读取缓存,关闭浏览器后,数据依然存在,此资源不会随着该页面的关闭而释放掉下次打开仍然会是from disk cache。
- 200 大小(如3.4k)
访问服务器,size显示为实际资源的大小
- 304 Not Modified
访问服务器,发现数据没有更新,服务器返回此状态码。然后从缓存中读取数据。这种在请求头中有两个请求参数:If-Modified-Since 和 If-None-Match。
状态码 | 类型 | 说明 |
200 | form memory cache | 不请求网络资源,资源在内存当中 |
200 | form disk ceche | 不请求网络资源,在磁盘当中 |
200 | 资源大小数值 | 从服务器下载最新资源 |
304 | 报文大小 | 请求服务端发现资源没有更新,使用本地资源 |
以上是chrome在请求资源是最常见的两种http状态码,由此可见样式表一般在磁盘中,不会缓存到内存中去,因为css样式加载一次即可渲染出网页。但是脚本却可能随时会执行,如果脚本在磁盘当中,在执行该脚本需要从磁盘中取到内存当中来,这样的IO开销是比较大的,有可能会导致浏览器失去响应。