啥都不说,先上图。
HTTP
1、定义
- 超文本传输协议:在两点之间传输超文本数据时需要遵守的规范
2、特点
- 无状态
- 请求应答模式
- 可靠
- 灵活
3、缺点
- 无状态:每个请求都是独立的,无需保存上下文信息,且每个请求必须携带请求所需的全部信息,导致单个消息结构复杂。
- 明文传输:有安全问题。存在被窃听、被篡改、被冒充风险(钓鱼网站)
- 队头阻塞:客户端能发起的请求个数是有限的,当同时发出的请求个数超出限制时,由于HTTP的请求应答模式导致必须等上一个请求应答之后下一个请求才能发出。
4、发展史
- 0.9
- 只支持get方法且
- 只能传输文字
- 1.0
- 可支持get、post、head方法
- 可传输文字、图片、视频、二进制等任何形式的数据
- 每次通信必须携带请求头信息
- 使用 If-Modified-Since 和 Expires字段控制缓存
- 不支持断点续传:传输过程中断的话,必须重头再来
- 请求头中不会携带域名host信息(因为通常一个服务器上只对应一个网站,所以不需要域名信息)
- 1.1
- 支持长连接,即复用同一个TCP连接:多个请求共用同一个TCP连接,但是必须等前一个请求响应后,后一个请求才能发出。此功能默认开启
- 管道机制:在同一个TCP连接中可以同时发送多个请求,不必等上一个请求响应后再发送下一个请求。但是服务器依然会按顺序响应请求。但由于实现上的缺陷,已经被废弃。
- 新增缓存字段: E-tag,If-Unmodified-Since, If-Match, If-None-Match
- 支持断点续传
- 支持虚拟主机:一个物理服务器上可以存在多个虚拟主机,它们共享一个IP地址,但域名不同。所以通过增加host字段区分不同主机。(host:www.baidu.com)
- 新增方法:PUT、 PATCH、 OPTIONS、 DELETE
- 引入Cookie和安全机制
- 存在问题
- TCP慢启动
- 无法占满带宽:同时开启多个TCP连接,导致这些连接竞争带宽。
- 队头阻塞问题
- 请求阻塞-发生在客户端
- 原因:浏览器允许同一个域名下建立多个TCP连接。但由于会对服务器造成压力,所以浏览器限制请求个数在6-8左右。
- 解决:使用域名分片技术解决TCP请求次数限制问题。比如把图片资源单独放在一个域名下面。
- 请求阻塞-发生在客户端
- 响应阻塞-发生在服务端(即应用管道机制)
- 原因:同时发送多个请求时,服务器会一个一个处理,上一个请求响应之后,才会处理下一个请求,如果有一个处理时间过长或者无法响应,就会造成后续请求无法处理。
- 2.0
- 多路复用
- 指的是在同一个TCP连接上同时发送多个请求,服务器响应请求时不必等上一个请求响应后再响应下一个。
- 通过引入流+帧概念解决HTTP队头响应阻塞问题:无需等待上一个请求完成再响应下一个,处理完一帧响应一帧,最后组装帧就好了。注意:不同ID的Stream是乱序的,对于同一个Stream ID的帧是按顺序传输的。
- 二进制分帧
- 请求头和请求体都使用二进制
- 好处:相比明文传输,方便计算机解析(因为是直接识别二进制数据,进行位运算)
- 头部压缩
压缩方法:静态字典(1-61)、动态字典(62-)、霍夫曼编码 - 支持服务器主动向客户端推送资源
在HTTP1.1中,要想服务器主动推送资源,需要借助websocket协议。 - 可设置请求优先级
- 通过一个域名只使用一个TCP长连接来传输数据,避免1.0的慢启动问题和多个连接竞争带宽问题。
- 存在问题
- 使用TCP协议导致的TCP队头阻塞问题
- TCP和TLS握手延迟
- 网络迁移需要重新连接
- 多路复用
- 3.0
- 使用udp+quic取代tcp
- 解决了TCP建立连接缓慢和队头阻塞问题
- 头部压缩算法由HPACK升级为QPACK
- 使用udp+quic取代tcp
5、状态码
- 1xx:请求正在处理
- 2xx:请求成功
- 200:请求成功,有资源返回
- 204:请求成功,但没有资源返回
- 206:客户端进行了范围请求
- 3xx:重定向
- 301:永久重定向
- 302:对象已移动
- 303:资源存在另一个URL,应使用GET方法请求资源
- 304:命中协商缓存
- 307:临时重定向,但不会改变请求方法
- 4xx:客户端发生错误
- 400:请求报文有错误
- 401:请求需要携带有HTTP认证的认证信息
- 404:服务器未找到资源
- 405:请求的方法不被允许
- 5xx:服务端错误
- 500:服务器内部错误
- 502:服务器自身正常,但访问时出现了问题
- 503:服务器暂时处于超负载或停机维护,无法处理请求
6、http请求包含哪几部分以及请求头字段含义
- 包含3部分:基础请求 - 请求标头 - 报文主体
-
基础请求:url | method | destIp
-
请求标头:配置 + 拦截器 => 权限、身份
- Accept - 请求内容的期望格式类型
- text/ html: HTML格式 / plain: 纯文本格式 / xml: XML格式
- image/ gif: gif格式 / jpeg: 图片格式 / png: png格式
- video/ mpeg / quicktime
- application/ xhtml+xml / atom+xml / json / pdf / msword / x-www-form-urlencoded
- Accept - 请求内容的期望格式类型
-
Accept-Encoding - 期望返回内容被压缩:减少网络流量,提升性能
- 要求而非强制,如果服务端不支持或者未开启压缩,则不起作用
- 服务端支持压缩,或者开启压缩。响应头中会有字段标识,Content-Encoding:gzip
- Accept-Language - 期望返回的语言类型(当然电脑上也要装了相应的语言包) => 国际化、多语言包
- zh 表示中文;zh-cn 表示简体中文;en、fr
- Connection - TCP信道的连接 keep-alive(1.1之后默认) / close
- 如何判断两个请求是否共用了一个TCP连接? connectionId - 代表单个请求新建立的信道索引(正式课信道建立与并发控制)
ps:这里用高铁和铁轨来比喻HTTP和TCP的例子很形象,长连接代表着多列高铁共用一条铁轨;短链接意味着每列火车都需要先建立自己的铁轨,然后再通行。这当然是很耗时的。长连接:多列单轨;短链接:单列单轨
- Cookie - 缓存形式
- 几种缓存的对比:cookie vs localStorage vs sessionStorage
- 大小:storage >> cookie
- 性能:cookie每次请求都会携带,影响性能 => 网络性能优化
- 跨域:cookie无法跨域调用,需要指定一个作用域 => 跨域问题
- 时效性:session - 当前页面;local - 跟随浏览器;cookie - 过期时间
- 跨tab共享:sessionStorage - 不支持;localStorage - 同源窗口共享;cookie - 同源窗口共享;
- 支持监听:session - 不支持跨页面,支持监听;local - 支持监听
- window.addEventListener("storage", e => {})
- 当前页面修改localStorage时,当前页面不会触发storage回调执行;如果另一个同源的页面监听了storage事件,那么这个页面会执行storage的回调
- 可用作性能监控 / 两个tab页,同步状态(登录态/文章内容实时更新)
- ①如何评估从A页面跳到B页面所消耗的时间? 分别在A、B页面通过localStorage埋点,打一个时间戳,计算差值即可。
- 几种缓存的对比:cookie vs localStorage vs sessionStorage
- Referer - 请求资源地址:eg:www.baidu.com/
- User-Agent - 用户侧信息
- 内容包含 - 操作系统 / 版本 、浏览器 / 版本、 设备信息(移动端)/ 版本
- 一般做兼容性处理会使用此字段
- Sec-Fetch-Dest\Sec-Fetch-Mode\Sec-Fetch-Site(考察的不多)
- mode - 请求的模式
- cors: 跨域请求
- no-cors: 限制请求
- same-origin: 同源请求
- navigate: 浏览器切换页面行为
- websocket: 建立websocket连接
- dest - 请求目标,如何使用获取的数据
- empty / iframe / font / image
- site - 请求发起者和资源之间的关系
- cross-site: 跨域请求
- same-origin: 发起方和目标一致
- none:用户操作的行为(点击图片、点击a标签)
- mode - 请求的模式
- q=0.01 - 参数优先级
- q越高代表优先级越高 0 =< q <= 1 [0, 1]
- 默认不写,优先级q = 1
-
其它get
- 监听是否用户是否扫码:轮询/长连接(用户端发出请求,但后端先不响应,直到用户扫码完成。长连接是限时的,超过了时间之后服务端返回失败态,提示用户需要更新二维码)
-
7、预检请求&跨域请求
- 简单请求:
- 请求方法:HEAD GET POST
- header只能包含accept、accept-language、content-language、content-type: x-www-form-urlencoded / form-data / text/plain
- 跨域请求
- 浏览器的安全策略 - 所以脱离浏览器之后,跨域问题不再存在。比如:服务端做http转发会存在跨域问题吗? 不会。
- 协议 / 域名 / 端口号 有一个不同时,就会产生跨域
- 浏览器对简单请求和非简单请求跨域时的不同处理方式
- 对于简单请求来说,请求跨域 => 放行请求发出 => 浏览器发出cors请求,并且携带origin
- 但是浏览器会拦截返回
- 浏览器检查response的header中有没有Access-Control-Allow-Origin,没有的话这次请求就中止。
- 对于非简单请求来说,请求跨域=> 浏览器会做一个http查询请求(预检请求)
- 预检请求
- 查询域名是否在服务器允许访问的名单中,是的话继续发起真正请求;不是的话返回错误给浏览器。
- 为什么要发送预检请求:对于简单请求,并不会包含用户端的任何信息。非简单请求就可能包括cookie等用户端信息了。预检请求只包含简单请求的那几个头,也不携带任何用户端的信息。如果不进行预检,直接发出非简单请求,用户端信息可能就会泄漏。
- 预检请求通过后需要关注的响应参数
- Access-Control-Allow-Origin: * (任意域名请求都可以被接收)/ Origin
- Access-Control-Allow-Credential: 是否允许发送cookie(一般用于打通登录态)
- 预检请求
- 对于简单请求来说,请求跨域 => 放行请求发出 => 浏览器发出cors请求,并且携带origin
- 跨域问题的解决方案
- 后端开启跨域配置,即把前端所在域加入到后端允许跨域访问的名单中
- 前端开发时通过devserver做跨域代理(vue支持)
- 这个代理只在本地开发时生效,打包到测试或线上环境之后就不生效了。
- 前端需要进行路由复写,但是路由复写后,request url并不会变
- 但是如果我们配置了路由前缀,还是会出现在请求中,所以后端也要做路由复写。(web.config.js)
- devserver是webpack本地开发服务器,配置后端API的代理服务,即把后端接口服务代理到本地的开发服务器地址。开发服务器收到请求后就会把请求转发到真正的服务器。因为跨域不能访问是浏览器的同源策略的政策, 也就是说服务器可以不遵守这个政策,也就是说服务器之间可以跨域共享资源。借助这一特性,我们可以进行代理转发,利用 node.js 监听 web 服务器开启的端口,并进行代理转发。
ps:此种处理跨域的方式更适合项目上线后前后端部署在同源地址下的情况,因为此种情况没必要让后端开启跨域配置。
8、缓存
- 如何设置:服务端开启,第一次发起请求时,服务器会在响应头中返回相关缓存策略,浏览器根据策略决定是否缓存资源。客户端发起第二次请求时,根据缓存策略,判断是否命中强缓存。没命中的话会把缓存字段添加到请求头中,向服务器发起请求,看是否命中协商缓存。
- 缓存的好处:不发起网络请求或发起请求但服务端不必响应数据
- 缓存类型
- 强缓存
- 字段
- Expires(响应头设置)
- Cache-Control(响应头或请求头中设置)
- public
- private
- no-store
- no-cache
- max-stale
- min-fresh
- max-age
- s-maxage
- 优先级:Cache-Control > Expires
- 返回状态码
- 200+from disk
- 200+from memory
- 客户端设置的Cache-control何时生效:只有客户端不想使用强缓存时才生效,即设置为no-store、no-cache、max-age=0
- 字段
- 协商缓存
- 字段
- Last-Modified(响应头)+If-modified-since
- 弊端
- 本地打开缓存文件,即使没有修改,Last-Modified的值也会改变,导致服务器返回旧资源
- 在不可感知的时间内修改了文件,导致服务器不返回最新资源
- 弊端
- ETag(响应头) + If-None-Match:ETag为资源的唯一指定标识,只要资源有变化,会发生变化。
- Last-Modified(响应头)+If-modified-since
- 优先级
- ETag>Last-Modified
- 性能
- ETag<Last-Modified
- 何时使用
- 强缓存失效时,浏览器携带缓存参数发起请求,由服务器经过判断后决定是否使用协商缓存
- 返回状态码
- 200 + 新资源
- 304
- 字段
- 缓存策略:强缓存优于协商缓存
- 用户行为对缓存的影响
- 地址栏输入地址:查找disk cache是否有匹配,如有则使用;如没有则发送网络请求。
- F5:因为 TAB 并没有关闭,因此 memory cache 是可用的,会被优先使用(如果匹配的话)。其次才是 disk cache。
- Ctrl+F5:不使用缓存,服务器直接返回资源
- 理论是这样,但是有时也会出现强刷之后不返回最新资源,这种情况只能勾选上浏览器的禁用缓存功能
- 缓存位置
- memory cache
- 内存中的缓存,读取速度高于硬盘,但缓存时间很短,Tab签关闭,缓存就会失效。操作系统缓存会存到这里。
- 注意:内存缓存在缓存资源时并不关心返回资源的HTTP缓存头Cache-Control是什么值,同时资源的匹配也并非仅仅是对URL做匹配,还可能会对Content-Type,CORS等其他特征做校验。
- disk cache
- 硬盘中的缓存,存活时间久,即使浏览器关闭,缓存依然存在。图像和网页一般缓存在这里
- 它会根据 HTTP Herder 中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期需要重新请求。
- push cache
- 其它三种缓存没有命中时,才使用。只在会话期间存在,一般缓存5分钟。
- service worker
- 运行在浏览器背后的独立线程,传输协议必须为HTTPS
- 好处:Service Worker的缓存与浏览器其他内建缓存机制不同,它让前端自由控制缓存哪些文件、如何匹配缓存、如何读取缓存、并且缓存是持续性的。
- 实现缓存的步骤:它实现缓存功能一般分为三个步骤:首先需要先注册sw,然后监听到install事件后就可以缓存需要缓存的文件,下次用户访问的时候就可以通过拦截请求的方式查询是否存在缓存,存在缓存的话直接读取缓存,否则就去请求数据。当sw未命中缓存时,需要调用fetch函数获取数据。也就是说,如果我们没有在sw中命中缓存的话,会根据缓存优先级去查找数据,但无论是从memory还是网络请求中获取的数据,浏览器都会显示我们时从sw中获取的内容。
- 使用步骤
- 注册
- 安装激活
- 自定义请求响应
- 更新
- memory cache
- 强缓存
9、HTTP如何解决无状态问题的
- cookie
- 缺点:信息存储在客户端,不安全
- session
- 缺点:信息存储在服务端,通过SessionId查找对应信息,SessionId仍然存在cookie中
- token
- 缺点:不再存储客户端信息,节省了服务器内存。但仍然需要去服务器查询校验认证信息。
- jwt
- 特点:三段式,信息不再存储在服务器端,全部都存在jwt本身上。
HTTPS
1、工作原理
- 使用非对称加密算法加密公钥 + 使用对称加密算法加密传输数据
- 在使用非对称加密时,需要先将公钥传输给另一端,在传输的过程中,这个公钥可能被中间人拦截。
- 使用对称加密算法的缺点:发送公钥的时候有可能被窃取
- 使用非对称加密算法(RSA算法)缺点:非常慢
2、与HTTP相比的优点
- HTTP是明文传输,HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。
- 利于SEO,谷歌、百度等会优先索引HTTPS网页
- HTTP 的端口号是 80,HTTPS 是 443
- HTTPS 需要到 CA 申请证书,一般免费证书很少,需要交费
3、如何解决HTTP的问题
- CA证书:解决冒充问题
- 信息加密:解决窃听问题
- 校验机制:解决篡改问题
CA证书包含:公钥、持有者信息、证书认证机构信息、CA对这份文件的数字签名以及使用方法、证书有效期、额外信息