HTTP 协议

2022-07-18  本文已影响0人  Drew_MyINTYRE

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 交流的信息不能被其它第三方窃听,篡改,伪装。

主要做了以下几件事:

  1. 客户端&服务端通信,协商加密方式

  2. 客户端(Client)和服务端(Server)互相确认身份

  3. 双方安全地交换 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

https://juejin.cn/post/6880024440143347719

https://zhuanlan.zhihu.com/p/80551769

上一篇下一篇

猜你喜欢

热点阅读