HTTP 1.0,2.0,3.0区别
[Http2.0的一些思考以及Http3.0的优势] blog.csdn.net/m0_60360320…
基本优化
影响一个 HTTP 网络请求的因素主要有两个:带宽和延迟。
- 带宽: 如果说我们还停留在拨号上网的阶段,带宽可能会成为一个比较严重影响请求的问题,但是现在网络基础建设已经使得带宽得到极大的提升,我们不再会担心由带宽而影响网速,那么就只剩下延迟了。
- 延迟:
-
- 浏览器阻塞(HOL blocking):浏览器会因为一些原因阻塞请求。浏览器对于同一个域名,同时只能有 4 个连接(这个根据浏览器内核不同可能会有所差异),超过浏览器最大连接数限制,后续请求就会被阻塞。
- DNS 查询(DNS Lookup):浏览器需要知道目标服务器的 IP 才能建立连接。将域名解析为 IP 的这个系统就是 DNS。这个通常可以利用DNS缓存结果来达到减少这个时间的目的。
- 建立连接(Initial connection):HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文,达到真正的建立连接,但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。
HTTPS与HTTP的一些区别
- HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费。
- HTTP协议运行在TCP之上,所有传输的内容都是明文,HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的。
- HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
- HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。
HTTP1.0和HTTP1.1的一些区别
-
缓存处理:HTTP1.1则引入了比HTTP1.0更多的缓存控制策略。例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等
-
带宽优化及网络连接的使用:
- HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能
- HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
-
错误通知的管理: HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
-
Host头处理: 在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
-
长连接:HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
HTTP2.0和HTTP1.X相比的新特性
- 二进制分帧传输(Binary Format)二进制分帧就是将一条连接上所有传输的信息,分割为更小的消息和帧(消息则是由一个或者多个帧组成的),并对他们采用二进制格式编码。首部信息放在Headers帧中,而主体信息被封装在Data帧中。而且在每个帧的首部都有一个标识位。
- 多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
- header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
- 服务端推送(server push),同SPDY一样,HTTP2.0也具有server push功能。
二进制分帧传输
为什么2.0可以对所有的内容进行二进制转换?
因为二进制分帧层是在应用层和传输层之间的中间层,所有的信息都会从中经过,进而可以转换。
为什要用二进制?
首先就是效率会更高,计算机最喜欢处理二进制数了。除此之外就是可以根据帧头部的八个位来定义额外的帧。除了数据帧和头部帧,实际上还有PING帧、SETTING帧、优先级帧等等,为之后的多路复用打上坚实的基础。
有什么其他的好处?
还可以在一个连接上实现双向数据流以及乱序发送。因为在,每一个帧上都有一个标记位。浏览器和服务端双方可以前期乱序接收消息和帧。接收完毕按照标记位的排列来拼接成一整条信息。所以,浏览器并行发送的请求,服务器可以并行返回,而不需要按照顺序返回。
多路复用
简单来说,多路复用技术也是可以并行发送请求,而且无需等待响应返回的一种技术。消除了不必要的延迟,减少页面的加载时间。
和1.0的长连接的区别在哪?
1.0默认开启长连接,也就是保持tcp的连接不中断,可以一直发送http请求。但是长连接只能发送串行的请求,也就是一问一答式的,如果前一个请求的响应没有被接收,那么第二个请求不会发送,就会造成阻塞。而多路复用就是在一条tcp连接上,请求可以并行发送,而无需等待前面的响应返回。
和1.0的管道的区别?
管道也可以并行发送请求,但是返回响应的顺序则必须是发送时候的顺序。例如,发送A,B,C三个请求,那么返回的顺序就是A,B,C哪怕A返回之前,B,C已经准备好,依然要等到A返回,也容易造成阻塞。
实际上,多路复用的基础就是二进制分帧,因为可以乱序发送和接收,所以就不必担心接收错误消息的问题,接收完毕直接拼接。
首部压缩
首部压缩实现的一个核心预设就是,在第一次请求之后,大部分的字段可以复用的。而且随着页面越来越复杂,同一个页面发出的请求会越来越多。如果头部不压缩的话,会造成很大的流量开销。
首部压缩的原理
支持http2.0的浏览器和服务器会维护一个相同的静态表和一个动态表,以及内置一个霍夫曼编码表。剩余的太复杂
服务器推送
简单来说,服务器可以对一个客户端请求发送多个响应,例如,浏览器向服务端请求index.html,里面包含一张样式表和一张图片。传统的方法就是会向浏览器发送三次请求。而服务端推送,则可以在一次请求内将这三个文件全部发送给浏览器,减少了请求次数,提升了网页性能。
不同域之间可以推送吗?
不可以。服务端推送也是遵守同源策略。
服务端推送有什么弊端?
如果服务端推送的内容,浏览器有缓存的话,就会浪费带宽。避免的方法就是在服务端配置,只对第一次请求实现服务器的推送。
** HTTP3.0和HTTP2.0相比的新特性**
- 连接迁移
- 无队头阻塞
- 自定义的拥塞控制
- 前向安全和前向纠错
连接迁移
先阐述一下tcp里面的四元组,一条tcp的唯一性标识,是由源IP,源端口,目的IP,目的端口,四元组标识。源IP,源端口一般比较稳定,但是目的IP,目的端口会由于网络元素等原因发生改变,一旦改变,那么此条tcp连接就会断开。
由于QUIC基于UDP协议,所以一条UDP协议不再由四元组标识,而是以客户端随机产生的一个64位数字作为ID标识。只要ID不变,那么这条UDP就会存在,维持连接,上层业务逻辑就感受不到变化。
无队头阻塞
http2.0的多路复用正好解决了http层的队头阻塞,但是tcp的队头阻塞依然存在。因为当数据包超时确认或者丢失,会等待重传,因此会阻塞当前窗口向右滑动,造成阻塞。
造成阻塞。而QUIC是基于udp的,创新点在于QUIC依靠一个严格的单调递增的packet序列,一个数据包里面还会有streamID和streamoffset偏移量,即使中途发生丢包或者超时确认,后面的数据包不会等待,等到接收完之后根据ID和offset即可完成重新拼装,从而避免了这种问题。
HTTP传输过程
[从输入URL到看到页面发生了什么?] juejin.cn/post/684490…
总共有六个过程
- DNS解析
- 建立TCP连接
- 发起HTTP请求
- 服务器处理HTTP请求并返回报文
- 浏览器解析渲染
- 结束连接
DNS解析过程
在输入www.google.com网址后,浏览器首先会在本地服务器中查找,如果没有则去根域名服务器查找,如果没有则去com顶级域名服务器查找,没有再去www.google.com域名服务器查找。如果找到了会缓存到本地,供下次使用。大致过程是 .
>>.com
google.com
~>www.google.com
DNS优化
DNS缓存
DNS存在多级缓存: 浏览器缓存,系统缓存(hosts文件),路由器缓存,IPS服务器缓存,根域名服务器缓存,顶级域名服务器缓存,主域名服务器缓存。
DNS负载均衡
访问一个网站时,每次响应的并不是同一个服务器(IP地址不同),DNS可以根据机器离用户的地理位置和机器的负载量返回一个合适的IP给用户,这就是DNS负载均衡。
TCP连接
三握四挥手
三次握手
第一次握手:
客户端发送syn包(Seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:
服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(Seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:
客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。
【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
【问题3】为什么不能用两次握手进行连接?
答:3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。
【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
Http缓存策略
目的
为了减少服务器压力,减少对服务器的请求,提升网站性能。
定义
确定Http响应是否可以被客户端缓存,以及哪些可以被缓存
流程
http请求时,会检测是否有本地缓存,如果本地命中了缓存会优先从本地取,如果没有本地缓存则浏览器再向服务器请求 (虽然本地可能有缓存,但却不一定会使用本地缓存,因为本地缓存可能是已经过期了的,为了鉴别是否过期就需要后面两种缓存规则结合) ,而http向服务器请求缓存规则分为两类: 强缓存, 协商缓存(对比缓存) 。
强缓存
直接从缓存服务器中取数据库的缓存数据,无需请求服务器。当缓存数据库中没有缓存的数据时才想服务端请求。
用来判断是否命中强缓存的字段为Expires
和 Cache-control
,cache-control
优先于Expires
,而这两个字段只是标记缓存是否过期,如果过期还需重新发送请求资源。
Expires
HTTP1.0的产物,现已过期
Expires返回绝对时间GMT格式字符串,如果客户端本地时间超过该时间就表示已经过期,需要重新请求
缺点: 时间可能不准确,客户端需要同步时间
Cache-control常用字段
public: 表示任何资源都缓存
no-cache: 表示每次使用本地缓存前都要向服务器请求(需要协商缓存),当服务器允许才使用本地缓存
private: 表示响应的结果只能被单个用户缓存
no-store: 表示禁止缓存
max-age=t: 表示t秒后缓存失效,t秒指我们的web中的文件被用户访问(请求)后的存活时间,是个相对的值,相对Request_time(请求时间).
\
协商缓存
又称对比缓存。客户端会先从缓存数据库拿到一个缓存的标识,然后向服务端验证标识是否失效,如果没有失效服务端会返回 304,这样客户端可以直接去缓存数据库拿出数据,如果失效,服务端会返回新的数据。
强制缓存的优先级高于协商缓存,若两种缓存皆存在,且强制缓存命中目标,则协商缓存不再验证标识。
协商缓存的标识
Last-Modified: 文件的修改时间
Last-Modified:服务器在响应请求时,会告诉浏览器资源的最后修改时间。
etag: 文件hash
每个文件有一个,改动文件了就变了,就是个文件hash,每个资源都会有这个东西
每次请求返回来 response header 中的 etag和 last-modified,在下次请求时在 request header 就把这两个带上,服务端把你带过来的标识进行对比,然后判断资源是否更改了,如果更改就直接返回新的资源,和更新对应的response header的标识etag、last-modified。如果资源没有变,那就不变etag、last-modified,这时候对客户端来说,每次请求都是要进行协商缓存了
HTTP状态码
2XX 成功状态码
3XX 重定向状态码
4XX客户端错误状态码
5XX服务器错误状态码
http 状态码 204 301 302 304 400 401 403 404 含义
- http 状态码 204 (无内容) 服务器成功处理了请求,但没有返回任何内容
- http 状态码 301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
- http 状态码 302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
- http 状态码 304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
- http 状态码 400 (错误请求) 服务器不理解请求的语法(一般为参数错误)。
- http 状态码 401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
- http 状态码 403 (禁止) 服务器拒绝请求。(一般为客户端的用户权限不够)
- http 状态码 404 (未找到) 服务器找不到请求的网页。
- 500 Internal Server Error(内部服务器错误)
- 501 Not Implemented(未实现)
- 502 Bad Gateway(网关故障)