初识 HTTP 协议 | 青训营笔记

83 阅读7分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天

课程重点

  1. HTTP 协议的基本定义
  2. HTTP 协议主要特征
  3. HTTP 协议发展历程
  4. HTTP 协议的报文结构

HTTP 协议的基本定义

HTTP 协议是 HyperText Transfer Protocol 的缩写,即超文本传输协议,它是一种基于 TCP/IP 通信协议来传递数据(HTML 文件,图片文件,查询结果等)的规则,由于 HTTP 协议属于应用层协议,所以它必须建立在 TCP/IP 协议之上,但是,它与 TCP/IP 协议又有所不同,它是一个独立的协议,但是它的设计参考了 TCP/IP 协议。

uTools_1674131421736.png

HTTP 协议主要特征

无状态

HTTP协议是无状态的,HTTP 协议自身不对请求和响应之间的通信状态进行保存,任何两次请求之间都没有依赖关系。直观地说,就是每个请求都是独立的,与前面的请求和后面的请求都是没有直接联系的。协议本身并不保留之前一切的请求或响应报文的信息。这是为了更快地处理大量事务,确保协议的可伸缩性,而特意将HTTP协议如此设计。

简单快速

在用户向服务器请求服务时,只需传送请求方法和路径,不需要发送额外过多的数据。请求方法常用的有GET、HEAD、PUT、DELETE、POST。每种方法规定了客户与服务器联系的类型不同。并且由于HTTP协议结构较为简单,使得HTTP服务器的程序规模小,因此通信速度很快。

灵活

HTTP协议对数据对象并没有要求,允许传输任意类型的数据对象。对于正在传输的数据类型,HTTP协议将通过Content-Type进行标记。

无连接

无连接的含义是对于连接加以限制,每次连接都只会对一个请求进行处理,当服务器对客户的请求处理完毕并收到客户的应答后,就会直接断开连接。HTTP协议采用这种方式可以大大节省传输时间,提高传输效率。

uTools_1674131698446.png

HTTP 协议发展历程

HTTP/0.9

在 1990 年 ,蒂姆·伯纳斯-李创建了运行万维网所需的所有工具,其中包括HTTP。那时候是互联网初期,计算机的处理能力包括网速等等都很弱,所以 HTTP 也逃脱不了那个时代的约束,因此设计的非常简单,而且也是纯文本格式。

因此只有 “GET”,也不需要啥请求头,并且拿完了就结束了,因此请求响应之后连接就断了。这时候的 HTTP 还没有版本号的,之所以称之为 HTTP / 0.9 是后人加上去了,为了区别之后的版本。

 

HTTP/1.0

随着图像和音频的发展,1995年Apache诞生(HTTP 服务器),浏览器也在不断的进步予以支持,这也促进了 HTTP 协议的修改。为了添加各种特性来满足用户的需求, 于 1996 年正式发布。

增加了以下几点:

  • 增加了 HEAD、POST 等新方法。
  • 增加了响应状态码。
  • 引入了头部,即请求头和响应头。
  • 在请求中加入了 HTTP 版本号。
  • 引入了 Content-Type ,使得传输的数据不再限于文本。

 

HTTP/1.1

从 1995 年至 1999 年间的第一次浏览器大战,极大的推动了 Web 的发展。主要是因为 HTTP/1.0 很大的性能问题,就是每请求一个资源都得新建一个 TCP 连接,而且只能串行请求

增加了以下几点:

  • 新增持久连接keep-alive,目的是复用TCP连接
  • 支持 pipeline,无需等待前面的请求响应,即可发送第二次请求
  • 允许响应数据分块(chunked),即响应的时候不标明Content-Length,客户端就无法断开连接,直到收到服务端的 EOF ,利于传输大文件。
  • 新增缓存的控制和管理。
  • 加入了 Host 头,用在你一台机子部署了多个主机,然后多个域名解析又是同一个 IP,此时加入了 Host 头就可以判断你到底是要访问哪个主机。

HTTP/1.1存在的问题

总结主要有以下两点:

  • 头阻塞:HTTP/1.1中只有收到当前请求响应后才能重用当前tcp连接发送下一次请求。虽然HTTP/1.1提出了pipeline,旨在缓解这个问题。但是一方面pipeline在复杂的网络环境下很难实现和普及,其次就算都用上了pipeline,pipeline也只是使得可以在本次响应完成之前可以发送下次请求,但响应依然要严格按照顺序返回,也就是如果前一个响应被阻塞,后边的响应将不会到来,头阻塞问题还是没有完全解决。目前客户端(比如浏览器)一般会同时打开多个tcp连接来绕开头阻塞的问题,chrome默认会打开6个tcp链接,并发请求各种类型数据。但是这就带来了一个矛盾,tcp链接越多,肯定对资源的浪费是越大的,链接越少,头阻塞的问题就会越突出。
  • 重复的未压缩头数据的传输:自HTTP/1.1之后,HTTP请求中通常带有大量ASCII编码的头部,这些头部通常大部分不会变化,需要每次请求都携带(尤其像是User Agent、Cookie这些值比较长的头部字段),会给本来就拥挤的网络带来很大的压力。

除此之外还有一些问题,比如TCP 的慢启动,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度,而大量http的业务请求其实本身都只是短链接的,所以导致tcp的流量控制算法没有很好的应用。为此,HTTP/2的出现就很有必要了。

 

HTTP/2.0

随着 HTTP/1.1 的发布,互联网也开始了爆发式的增长,这种增长暴露出 HTTP 的不足,主要还是性能问题,而 HTTP/1.1 无动于衷。互联网标准化组织以 Google 推出的SPDY 协议为基础开始制定新版本的 HTTP 协议,最终在 2015 年发布了 HTTP/2。

增加了以下几点:

  • 二进制协议,不再是纯文本。(解析数据开销更小,减少了网络延迟,提升了整体的吞吐量)
  • 支持一个 TCP 连接发起多请求,即支持多路复用,移除了 pipeline。(HTTP/1.1 pipeline 还是有阻塞的情况,需要等前面的一个响应返回了后面的才能返回。)
  • 利用 HPACK 压缩头部(减少数据传输量。)
  • 允许服务端主动推送数据。(其实就是减少了请求的次数)

HTTP/2 引入了一个新的二进制分帧层,该层无法与之前的 HTTP/1.x 服务器和客户端兼容,HTTP/2的新特性都是建立在这个二进制分帧层基础之上的。

 

HTTP/3.0

这次的痛点来自于 HTTP 依赖的是可靠的、有序的,具有失败重传和按序机制的传输协议 TCP。

依赖TCP存在的问题:

  1. HTTP/2 是所有流共享一个 TCP 连接,所以会有 TCP 层面的队头阻塞,当发生重传时会影响多个请求响应;
  2. TCP 是基于四元组(源IP,源端口,目标IP,目标端口)来确定连接的,而在移动网络的情况下 IP 地址会频繁的换,这会导致反复的建连;
  3. TCP 与 TLS 的叠加握手,增加了延时

因此 Google 把 TCP 可靠、有序、丢包重传和拥塞控制功能提到应用层来实现,就研究出了基于 UDP 的 QUIC 协议。在 2018 年,互联网标准化组织 IETF 提议将 HTTP over QUIC 更名为 HTTP/3 并获得批准。

增加了以下几点:

  • 基于UDP,并把 TCP 可靠、有序、丢包重传和拥塞控制功能提到应用层来实现;
  • 引入了个叫 Connection ID 来标识一个链接,所以切换网络之后可以复用这个连接,达到 0 RTT 就能开始传输。
  • 开发了QPACK 压缩头部,也采用了静态表、动态表和哈夫曼编码。(因为无法使用依赖TCP的HPACK)

HTTP 协议的报文结构

请求方式

uTools_1674131794924.png

常用请求头

uTools_1674134082385.png

场景分析

静态资源

uTools_1674134212008.png

登录案例

uTools_1674134253390.png

ajax与xhr

uTools_1674134332110.png

node http模块

uTools_1674134349675.png

扩展通信WebSocket

uTools_1674134383983.png