前言
Http
协议是我们开发中的必备知识,也是面试中的常客
本文从几个问题出发梳理Http
相关知识点,以便快速构建Http
知识体系,如果对你有用,欢迎点赞~
本文主要包括以下内容
-
Http
到底是什么? -
Http
协议为什么是无状态的? - 什么是队头阻塞问题?
-
GET
,POST
,PUT
等方法有什么区别? - 为什么引入
Https
? - 为什么引入
Http2.0
? - 为什么引入
Http3.0
? - 浏览器输入
url
后发生了什么?
本文目录如下所示
image.png1. Http
到底是什么?
Http
翻译过来就是超文本传输协议,它的主要作用就是在客户端与服务端之间进行通信
我们平常在浏览器查看网页时就用到了Http
协议,根据浏览器地址栏中指定的URL
,Web
浏览器从Web
服务器端获取文件资源(resource
)等信息,从而显示出 Web
页面。
Http
协议主要具有以下特点
- 无连接:每一次请求都要连接一次,请求结束就会断掉,不会保持连接
- 无状态:每一次请求都是独立的,请求结束不会记录连接的任何信息,减少了网络开销,这是优点也是缺点
- 灵活:通过
http
协议中头部的Content-Type
标记,可以传输任意数据类型的数据对象(文本、图片、视频等等),非常灵活 - 简单快速:发送请求访问某个资源时,只需传送请求方法和
URL
就可以了,使用简单,正由于http
协议简单,使得http
服务器的程序规模小,因而通信速度很快
当然Http
协议也有一些缺点
- 无状态:请求不会记录任何连接信息,没有记忆,就无法区分多个请求发起者身份是不是同一个客户端的,意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大
- 明文传输:
Http
报文使用明文传输,如果在通信的过程中存在中间人,可以轻易的获取请求的所有内容 - 队头阻塞:当开启长连接时,多个
Http
请求复用一个TCP
连接,同一时刻只能处理一个请求,那么当前面的请求耗时过长时,其他请求就只能处于阻塞状态
2. Http
协议为什么是无状态的?
上面我们介绍了Http
协议是无状态的,即每次请求都是独立的,服务端中不保存客户端的状态
因此为了区分用户的身份,我们需要每次都在Header
中携带身份信息(比如Cookie
),这样其实导致了每次连接传送的数据量变大了不少。
那么为什么Http
要这样设计呢?
-
http
最初设计成无状态的是因为只是用来浏览静态文件的,无状态协议已经足够,也没什么其他的负担。 - 随着
web
的发展,它需要变得有状态,但是不是就要修改http
协议使之有状态呢?是不需要的。因为我们经常长时间逗留在某一个网页,然后才进入到另一个网页,如果在这两个页面之间维持状态,代价是很高的。 - 其次,老版本
http
是无状态的,但是现在对http
提出了新的要求,按照软件领域的通常做法是,兼容历史版本,在http
协议上再加上一层实现我们的目的。所以引入了cookie
、session
等机制来实现这种有状态的连接。 - 同时,保存用户状态是一个很复杂的过程,而
Http
协议为了更快地处理大量事务,确保协议的可伸缩性,故意把HTTP
协议设计的比较简单。因此没有必要在Http
协议中引入状态管理
3. 什么是队头阻塞问题?
Http1.0
是无连接的,即每个请求/应答客户与服务器都要新建一个连接,完成之后立即断开连接
在Http1.1
中引入了Keep-Alive
支持长连接,即多个Http
请求复用一个TCP
连接,如下图所示:
如上所示,使用长连接,可以减少TCP
握手时间,提高请求速度
但是在长连接下同样Http
协议同样会有队头阻塞问题,因为我们虽然可以复用TCP
连接,但Http
请求仍然是串行的
请求1 -> 响应1 -> 请求2 -> 响应2 -> 请求3 -> 响应3
如上所示,就是这样一个先进先出的串行队列,没有轻重缓急的优先级,只有入队的先后顺序,排在最前面的请求最先处理,就导致如果队首的请求耗时过长,后面的请求就只能处于阻塞状态,这就是队头阻塞问题
当然我们也可以通过一些方式缓解这个问题
- 一个域名允许分配多个长连接,就相当于增加了任务队列,不至于一个队列里的任务阻塞了其他全部任务。现在的浏览器标准中一个域名并发连接可以有
6~8
个(Chrome
6个/Firefox
8个) - 一个域名最多可以并发
6~8
个,那我们可以使用多个二级域名,当我们访问服务端时,可以让不同的资源从不同的二域名中获取,而它们都指向同一台服务器,这样能够并发更多的长连接了,从而减少队头阻塞
4. GET
,POST
,PUT
等方法有什么区别?
4.1 GET
与POST
的区别
-
GET
用于获取信息,是无副作用的,是幂等的,且可缓存. -
POST
用于修改服务器上的数据,有副作用,非幂等,不可缓存
其实GET
与POST
的区别主要就是这些,网上有些文章说GET
的URL
长度有限制,HTTP
协议没有Body
和 URL
的长度限制,对 URL
限制的大多是浏览器和服务器的原因。
浏览器原因就不说了,服务器是因为处理长URL
要消耗比较多的资源,为了性能和安全(防止恶意构造长URL
来攻击)考虑,会给URL
长度加限制。
4.2 PUT
与POST
的区别
有人说,PUT
与POST
的区别在于POST
是用来创建数据的,PUT
是用来更新数据的.
其实PUT
与POST
都能创建数据,它们的主要区别是PUT
是幂等的,而POST
不是幂等的
因此PUT
能用于更新数据,也能用于创建数据,而POST
只能用于创建数据
如果POST
两条相同的数据,则会创建两条数据
而PUT
两条相同的数据,则只会创建一条数据
5. 为什么引入Https
?
上面说到了HTTP
是明文传输的,在安全方面主要有以下缺点
-
Http
通信使用明文(不加密),内容可能会被窃听 - 不验证通信方的身份,因此有可能遭遇伪装
- 无法证明报文的完整性,所以有可能已遭篡改
正因此才推出了Https
协议来保证Client
和Server
交流的信息不能被其它第三方窃听及防止篡改与伪装
Https
通信的主要过程如图所示:
主要做了以下几件事
1.客户端&服务端通信,协商加密方式
2.客户端(Client
)和服务端(Server
)互相确认身份
3.双方安全地交换https
通信使用的密钥(Session Key
)
Https
加密的具体流程比较复杂,里面还涉及到证书链校验,中间人攻击等知识点
我之前总结过一篇文章,这里就不缀述了,有兴趣的同学可以了解下:Android程序员需要了解的https与中间人攻击
6. 为什么引入Http2.0
?
上面我们已经介绍了Http
协议的主要缺点
1.请求 / 响应头部(Header
)未经压缩就发送,首部信息越多延迟越大。
2.发送冗长的首部。每次互相发送相同的首部造成的浪费较多;
3.服务器是按请求的顺序响应的,如果服务器响应慢,会招致客户端一直请求不到数据,也就是队头阻塞;
4.没有请求优先级控制;
5.请求只能从客户端开始,服务器只能被动响应
Http2.0
正是为了解决以上问题才被引入的,相比Http1.1
,Http2.0
主要有以下改进
6.1 头部压缩
HTTP/2
会压缩头(Header
)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分。
这就是所谓的HPACK
算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了
6.2 多路复用
6.2.1 二进制分帧
HTTP/2
不再像HTTP/1.1
里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame
):头信息帧和数据帧。
这样虽然对人不友好,但是对计算机非常友好,因为计算机只懂二进制,那么收到报文后,无需再将明文的报文转成二进制,而是直接解析二进制报文,这增加了数据传输的效率
6.2.2 多路复用解决队头阻塞
原来Headers + Body
的报文格式如今被拆分成了一个个二进制的帧,用Headers
帧存放头部字段,Data
帧存放请求体数据。
分帧之后,服务器看到的不再是一个个完整的 HTTP
请求报文,而是一堆乱序的二进制帧。
通信双方都可以给对方发送二进制帧,这种二进制帧的双向传输的序列,也叫做流(Stream
)。
HTTP/2
用流(Stream
)来在一个 TCP
连接上来进行多个数据帧的通信,这就是多路复用的概念。
这些二进制帧不存在先后关系,因此也就不会排队等待,也就没有了 HTTP
的队头阻塞问题。
举例来说,在一个 TCP
连接里,服务器收到了客户端 A
和 B
的两个请求,如果发现 A
处理过程非常耗时,于是就回应 A
请求已经处理好的部分,接着回应 B
请求,完成后,再回应 A
请求剩下的部分。
6.5 服务器推送
HTTP/2
还在一定程度上改善了传统的「请求 - 应答」
工作模式,服务不再是被动地响应,也可以主动向客户端发送消息。
举例来说,在浏览器刚请求 HTML
的时候,就提前把可能会用到的 JS
、CSS
文件等静态资源主动发给客户端,减少延时的等待,也就是服务器推送
7. 为什么引入Http3.0
?
Http2.0
还没学,怎么Http3.0
又来了?
总得来说,这是因为Http2.0
还存在一定的缺陷
HTTP/2
主要的问题在于,多个 HTTP
请求在复用一个 TCP
连接,下层的 TCP
协议是不知道有多少个 HTTP
请求的。
所以一旦发生了丢包现象,就会触发 TCP
的重传机制,这样在一个 TCP
连接中的所有的 HTTP
请求都必须等待这个丢了的包被重传回来。
HTTP/2
多请求复用一个TCP
连接,一旦发生丢包,就会阻塞住所有的 HTTP
请求。
可以看出,这其实不是Http
协议的问题,而是传输层协议的问题
所以 HTTP/3
把 HTTP
下层的 TCP
协议改成了 UDP
!
UDP
发生是不管顺序,也不管丢包的,所以不会出现 HTTP/1.1
的队头阻塞 和 HTTP/2
的一个丢包全部重传问题。
大家都知道 UDP
是不可靠传输的,但基于 UDP
的 QUIC
协议 可以实现类似 TCP
的可靠性传输。
QUIC
是一个在 UDP
之上的伪 TCP
+ TLS
+ HTTP/2
的多路复用的协议,在这里就不详细介绍了,有兴趣的同学可参考:QUIC协议连接过程介绍
总得来说,QUIC
是新协议,对于很多网络设备,根本不知道什么是 QUIC
,只会当做 UDP
,这样会出现新的问题。
所以 HTTP/3
现在普及的进度非常的缓慢,大家只做简单了解即可。
8. 浏览器输入url
后发生了什么?
这个是面试中的常见问题了,我们在了解了上面的知识点后,再一起来看下这个问题
要回答这个问题,我们需要对TCP/IP
协议族有一定的了解
8.1 Tcp/IP
协议族
TCP/IP
协议族里重要的一点就是分层。
TCP/IP
协议族按层次分别分为以下 4 层:应用层、传输层、网络层和数据链路层。
把 TCP/IP
层次化是有好处的。比如,如果互联网只由一个协议统筹,某个地方需要改变设计时,就必须把所有部分整体替换掉。
而分层之后只需把变动的层替换掉即可。把各层之间的接口部分规划好之后,每个层次内部的设计就能够自由改动了。
值得一提的是,层次化之后,设计也变得相对简单了。
处于应用层上的应用可以只考虑分派给自己的任务,而不需要弄清对方在地球上哪个地方、对方的传输路线是怎样的、是否能确保传输送达等问题。
8.1.1 应用层
应用层决定了向用户提供应用服务时通信的活动。
TCP/IP
协议族内预存了各类通用的应用服务。比如,FTP
(File Transfer Protocol
,文件传输协议)和 DNS
(Domain Name System
,域名系统)服务就是其中两类。
HTTP
协议也处于该层。
8.1.2 传输层
传输层对上层应用层,提供处于网络连接中的两台计算机之间的数据传输。
在传输层有两个性质不同的协议:TCP
(Transmission ControlProtocol
,传输控制协议)和 UDP
(User Data Protocol
,用户数据报协议)。
8.1.3 网络层
网络层用来处理在网络上流动的数据包。数据包是网络传输的最小数据单位。
该层规定了通过怎样的路径(所谓的传输路线)到达对方计算机,并把数据包传送给对方。
与对方计算机之间通过多台计算机或网络设备进行传输时,网络层所起的作用就是在众多的选项内选择一条传输路线。
IP
协议就在网络层
8.1.4 数据链路层
用来处理连接网络的硬件部分。
包括控制操作系统、硬件的设备驱动、NIC
(Network Interface Card
,网络适配器,即网卡),及光纤等物理可见部分(还包括连接器等一切传输媒介)。
硬件上的范畴均在链路层的作用范围之内。
8.2 浏览器输入url
后大致流程
- 解析用户输入的
Url
- 通过
DNS
协议根据域名查询ip
地址 - 客户端发起请求
- 服务端接受请求并处理
- 客户端接受响应
- 浏览器渲染页面
这里我们主要关注客户端发起请求及服务端接受请求的过程,这里就用到了TCP/IP
协议族
在发送数据时,每层都要对数据进行封装,在接收数据时,每层都要对数据进行解封,如下图所示:
简单来说,就是从应用层发http
请求,到传输层通过三次握手建立tcp
连接,再到网络层的ip
寻址,再经过数据链路层与物理层,最后到达服务端。 然后服务端经过相反的过程,在每一层将数据取出来即可。
关于浏览器输入url
后的流程我们这里没有讲得很详细,想要了解更多细节的同学可参考:在浏览器输入 URL 回车之后发生了什么(超详细版)
总结
本文主要梳理了Http
协议相关知识点,并回答了以下问题
-
Http
到底是什么? -
Http
协议为什么是无状态的? - 什么是队头阻塞问题?
-
GET
,POST
,PUT
等方法有什么区别? - 为什么引入
Https
? - 为什么引入
Http2.0
? - 为什么引入
Http3.0
? - 浏览器输入
url
后发生了什么?
如果对您有所帮助,欢迎点赞,谢谢~
参考资料
20分钟助你拿下HTTP和HTTPS,巩固你的HTTP知识体系
Http协议为什么是无状态的
What is the difference between POST and PUT in HTTP?
图解网络: HTTP 常见的面试题
在浏览器输入 URL 回车之后发生了什么(超详细版)
网友评论