Http 协议为什么是无状态的?
Http 协议是无状态的,即每次请求都是独立的,服务端中不保存客户端的状态
因此为了区分用户的身份,我们需要每次都在 Header 中携带身份信息(比如Cookie),这样其实导致了每次连接传送的数据量变大了不少。
那么为什么 Http 要这样设计呢?
http 最初设计成无状态的是因为只是用来浏览静态文件的,无状态协议已经足够,也没什么其他的负担。但是现在对 http 提出了新的要求,按照软件领域的通常做法是,兼容历史版本,在 http 协议上再加上一层实现我们的目的。所以引入了 cookie、session 等机制来实现这种有状态的连接。
什么是队头阻塞问题?
Http1.0 是无连接的,即每个请求/应答客户与服务器都要新建一个连接,完成之后立即断开连接,在 Http1.1 中引入了 Keep-Alive
支持长连接,即多个 Http 请求复用一个 TCP 连接,
如上所示,使用长连接,可以减少 TCP 握手时间,提高请求速度
但是在长连接下同样 Http 协议同样会有队头阻塞问题,因为我们虽然可以复用TCP 连接,但 Http 请求仍然是串行的,请求1 -> 响应1 -> 请求2 -> 响应2 -> 请求3 -> 响应3
,这样一个先进先出的串行队列,没有轻重缓急的优先级,只有入队的先后顺序,排在最前面的请求最先处理,就导致如果队首的请求耗时过长,后面的请求就只能处于阻塞状态,这就是队头阻塞问题。
我们可以通过一些方式缓解这个问题:
一个域名允许分配多个长连接,就相当于增加了任务队列,不至于一个队列里的任务阻塞了其他全部任务。现在的浏览器标准中一个域名并发连接可以有6~8个(Chrome6个/Firefox8个),我们可以使用多个二级域名,当我们访问服务端时,可以让不同的资源从不同的二域名中获取,而它们都指向同一台服务器,这样能够并发更多的长连接了,从而减少队头阻塞。
http 协议不限制 url 长度?
其实 http 1.1 协议中对 url 的长度是不受限制的。协议原文:
The HTTP protocol does not place any a priori limit on the length of a URI. Servers MUST be able to handle the URI of any resource they serve, and SHOULD be able to handle URIs of unbounded length if they provide GET-based forms that could generate such URIs. A server SHOULD return 414 (Request-URI Too Long) status if a URI is longer than the server can handle (see section 10.4.15).
HTTP 协议不对 URI 的长度作事先的限制,服务器必须能够处理任何他们提供资源的URI,并且应该能够处理无限长度的 URIs,这种无效长度的 URL 可能会在客户端以基于 GET 方式的请求时产生。如果服务器不能处理太长的 URI 的时候,服务器应该返回414状态码(此状态码代表 Request-URI 太长)。
虽然协议中未明确对 url 进行长度限制,但在真正实现中,url 的长度还是受到限制的,一是服务器端的限制,二就是浏览器端的限制。
服务器是因为处理长 URL 要消耗比较多的资源,为了性能和安全(防止恶意构造长 URL 来攻击)考虑,会给 URL 长度加限制。
浏览器的种类繁多,并且对 URL 的长度限制是有所差异的,具体如下:
GET, POST, PUT 等方法有什么区别?
1,GET 用于获取信息,且可缓存
2,POST 用于修改服务器上的数据,不可缓存
3,PUT 能用于更新数据,也能用于创建数据,而 POST 只能用于创建数据
如果 POST 两条相同的数据,则会创建两条数据;而 PUT 两条相同的数据,则只会创建一条数据。
为什么引入 Https?
HTTP 是明文传输的,在安全方面主要有以下缺点:
1,Http 通信使用明文(不加密),内容可能会被窃听
2,不验证通信方的身份,因此有可能遭遇伪装
3,无法证明报文的完整性,所以有可能已遭篡改
正因此才推出了 Https 协议来保证 Client 和 Server 交流的信息不能被其它第三方窃听,篡改,伪装。
主要做了以下几件事:
-
客户端&服务端通信,协商加密方式
-
客户端(Client)和服务端(Server)互相确认身份
-
双方安全地交换 https 通信使用的密钥(Session Key)
Https 加密的具体流程比较复杂,里面还涉及到证书链校验,中间人攻击等知识点
为什么引入 Http2.0?
1,头部压缩
如果你同时发出多个请求,他们的头是一样的或是相似的,那么,2.0协议会帮你消除重复的部分。这就是所谓的
HPACK
算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
2,多路复用
原来
Headers + Body
的报文格式如今被拆分成了一个个二进制的帧,用Headers
帧存放头部字段,Data
帧存放请求体数据。分帧之后,服务器看到的不再是一个个完整的 HTTP 请求报文,而是一堆乱序的二进制帧。通信双方都可以给对方发送二进制帧,这种二进制帧的双向传输的序列,也叫做流(Stream)。HTTP/2 用流(Stream)来在一个 TCP 连接上来进行多个数据帧的通信,这就是多路复用的概念。这些二进制帧不存在先后关系,因此也就不会排队等待,也就没有了 HTTP 的队头阻塞问题。
举例来说,在一个 TCP 连接里,服务器收到了客户端 A 和 B 的两个请求,如果发现 A 处理过程非常耗时,于是就回应 A 请求已经处理好的部分,接着回应 B 请求,完成后,再回应 A 请求剩下的部分。
3,服务器主动推送
HTTP/2 还在一定程度上改善了传统的「请求 - 应答」工作模式,服务不再是被动地响应,也可以主动向客户端发送消息。举例来说,在浏览器刚请求 HTML 的时候,服务器就提前把可能会用到的 JS、CSS 文件等静态资源主动发给客户端,减少延时的等待,也就是服务器推送。
为什么引入 Http3.0?
HTTP/2 主要的问题在于,多个 HTTP 请求在复用一个 TCP 连接,下层的 TCP 协议是不知道有多少个 HTTP 请求的。所以一旦发生了丢包现象,就会阻塞住所有的 HTTP 请求,就会触发 TCP 的重传机制,这样在一个 TCP 连接中的所有的 HTTP 请求都必须等待这个丢了的包被重传回来。可以看出,这其实不是Http 协议的问题,而是传输层协议的问题,所以 HTTP/3 把 HTTP 下层的 TCP 协议改成了 UDP!
UDP 是不可靠传输,不管顺序,也不管丢包的。
了解一下 TCP/IP 协议 分层
TCP/IP 协议族按层次分别分为以下 4 层:应用层、传输层、网络层和数据链路层。分层之后,某一层需要改变设计时,只需把变动的层替换掉即可。把各层之间的接口部分规划好之后,每个层次内部的设计就能够自由改动了。层次化之后,设计也变得相对简单了。
1,应用层
TCP/IP 协议族内预存了各类通用的应用服务。比如,FTP(File Transfer Protocol,文件传输协议)和 DNS(Domain Name System,域名系统)服务就是其中两类。HTTP 协议也处于该层。
2,传输层
提供处于网络连接中的两台计算机之间的数据传输。在传输层有两个性质不同的协议:TCP(Transmission ControlProtocol,传输控制协议)和 UDP(User Data Protocol,用户数据报协议)。
3,网络层
网络层用来处理在网络上流动的数据包。数据包是网络传输的最小数据单位。
该层规定了通过怎样的路径(所谓的传输路线)到达对方计算机,并把数据包传送给对方。与对方计算机之间通过多台计算机或网络设备进行传输时,网络层所起的作用就是在众多的选项内选择一条传输路线。IP 协议就在网络层。
4,数据链路层
用来处理连接网络的硬件部分。包括控制操作系统、硬件的设备驱动、NIC(Network Interface Card,网络适配器,即网卡),及光纤等物理可见部分(还包括连接器等一切传输媒介)。硬件上的范畴均在链路层的作用范围之内。
浏览器输入 url 后发生了什么?
1,解析用户输入的 Url
2,通过 DNS 协议(应用层)根据域名查询 ip 地址
3,客户端发起请求
4,服务端接受请求并处理
5,客户端接受响应
6,浏览器渲染页面
简单来说,就是从应用层发 http 请求,到传输层通过三次握手建立 tcp 连接,再到网络层的 ip 寻址,再经过数据链路层与物理层,最后到达服务端。 然后服务端经过相反的过程,在每一层将数据取出来即可。
Ref:
https://juejin.cn/post/7001839784289108005
网友评论