当前位置: 首页 > article >正文

HTTP协议解析(http/1、2、3)

什么是 HTTP?

HTTP(超文本传输协议)是在全球网络上最通用数据通信的方式。有三个主要的版本,我们将在这里逐个介绍。

简单来说,该协议定义了浏览器如何与服务器进行通信以传递数据。在所有版本的协议中,浏览器会主动请求某些内容(“Request”),服务器会被动响应数据回来(“Response”)。

HTTP/1 于 1996 年推出。在那之前,有 HTTP/0.9,这是一个简单的协议,只支持 GET 方法,没有头部信息。HTTP 响应中只包括 HTML 文档。没有 HTTP 头部,也没有 HTTP 状态码。

HTTP/1.0 添加了头部信息、状态码以及额外的方法,如 POST 和 HEAD。然而,HTTP/1 仍然存在一些限制。例如,每个请求-响应对都需要一个新的 TCP 连接。

1997 年,为了解决 HTTP/1 的限制,发布了 HTTP/1.1,这个版本是 HTTP1 的权威版本,支持了Keepalive与Pipeline。这个版本推动了互联网的快速增长,尽管已经超过 25 年的历史,仍然被广泛使用。

如下是一个简单的HTTP请求

GET / HTTP/1.1
Host: www.baidu.com

服务端接收到请求后,响应html文档

HTTP/1.1 200 OK
<!DOCTYPE html>
<a href=http://home.baidu.com>关于百度</a>
</html>

在响应的html文档中,还包含各种资源,包括图片,js,css文档等等

HTTP/1.x的特性

持久连接

正如前面提到的,HTTP/1.1之前都是一种单请求-响应的协议。客户端打开与服务器的连接,发出请求,然后获取响应,连接随后关闭。如果有第二个请求,该循环将重复。对于后续的请求,同样的循环会重复。

随着网络资源向媒体发展,每次在每次响应后关闭连接显得很浪费。如果一个网页包含多个需要获取的资源,您将不得不多次打开和关闭连接。

由于 HTTP/1 是建立在 TCP协议之上的,每次新连接都意味着要经历TCP的三次握手过程。

HTTP/1.1 支持了Keepalive的特性,来规避了这个问题。它规定了在HTTP请求之后不需要关闭TCP连接,除非明确告知需要关闭。这意味着:

  • 每个请求后不关闭连接。
  • 没有多次的 TCP 握手。

Pipeline

HTTP/1.1 还引入了流水线处理(pipeline)的概念。

其想法是允许客户端在单个 TCP 连接上发送多个请求,而无需等待相应的响应。例如,当浏览器发现它需要两个图像来呈现一个网页时,它可以一个接一个地请求它们。

Pipeline通过减少每个响应之前的延迟,进一步提高了性能。但是Pipeline仍然存在头部阻塞的问题。

Range的分片传输

HTTP/1.1 引入了分片传输特性(chunked transfer encoding),允许服务器将响应分成较小的片发送,而不是等待整个响应生成完毕。

这使得初始页面渲染更快,特别是对于大型或动态生成的内容,比如视频播放场景,就大量使用了range请求,提高用户体验。

缓存

HTTP/1.1 引入了复杂的HTTP缓存机制

它添加了诸如 Cache-Control 和 ETag 等头部信息,允许客户端和服务器更好地管理缓存内容,减少不必要的数据传输。并支持如 If-Modified-Since 和 If-None-Match 等Header,允许客户端发送缓存有效性的探测请求,只有在内容发生修改之后,才会请求和发送完整的资源内容,节约带宽并响应速度。

HTTP/1.1的问题

串行请求

http/1.x及之前的版本,都是一个请求-一个响应,得上一个请求完成之后才能进行下一次请求。

头部阻塞

http/1.x中一个请求一个响应,每一次的情况都需要关闭连接。后来使用了Keepalive支持在一个TCP连接中发送多个HTTP请求,不过也只会保持一段时间。

在http/1.1中为了解决串行请求的问题,支持了Pipeline。发送端发送多个http请求的时候,不需要等待服务端响应,就可以顺序地的继续发送后续内容。但是pipeline仍然需要保证顺序。接收端必须按顺序接收,如果有之前发送的请求接收端没有完成接收,如发生了丢包,那后续的请求就无法接收,这就是http/1.1中的头部阻塞。

缺乏优先级设置

HTTP/1.x 没有提供请求优先级的方式,可能导致次要资源阻塞重要资源。

HTTP头部占用大

HTTP请求及响应的发送,除了数据之外,需要发送大量纯文本头部信息,尤其在使用 cookie 时。

HTTP/2-解决了性能问题

随后于2015年发布了 HTTP/2,HTTP/2 中引入了多个特性来解决HTTP/1.1中碰到的性能问题。

多路复用

看看我们在 HTTP/1.1 中上面的例子,在这个例子中,您的浏览器请求一个包含多个资源的文档。在 HTTP/1.1 中,这些资源请求被排队,并逐个请求。

在 HTTP/2 中,情况有些不同。使用多路复用,浏览器可以在一个连接上一起请求这些资源,然后以相同的方式接收它们。

头部压缩

HTTP/2 使用 HPACK 算法来压缩请求和响应头部,通过静态字典,动态字典及Huffman编码来对HTTP头部进行压缩,显著减少了头部大小,减少了传输的数据量。

二进制分帧

帧:帧是 HTTP/2 数据通信消息的最小单位,例如请求和响应等,一个消息由一个或多个帧组成。

流:存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一流ID。

HTTP/2 采用二进制格式传输数据,而非 HTTP 1.x 的文本格式,二进制协议解析起来更高效。HTTP / 1 的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。

HTTP/2 中,同域名下所有通信都在单个连接上完成,该连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,接收端根据帧首部的流标识可以重新组装。

流优先级

在HTTP/2中,每个数据流都有一个唯一的ID,并且可以被分配一个优先级。这个优先级告诉网络服务器和客户端,在处理多个数据流时,应该先处理哪个。优先级高的数据流会优先获得网络资源,从而更快地完成传输。

服务器推送

HTTP/2支持服务端在被请求之前主动将资源推送到客户端的缓存中,减少延迟,提高整体用户体验。

HTTP/2的问题

HTTP/2虽说已经没有了HTTP/1.1中的对头阻塞的问题,但是因为HTTP/2依然是构建在TCP协议之上的。TCP本身仍然存在对头阻塞的问题,并且TCP本身在弱网条件、网络频繁切换的情况下,TCP的本身的性能仍然对HTTP/2有着一定的影响。

HTTP/3

HTTP/3 保留了从 HTTP/2 中的语法和语义,但是HTTP/3不再依赖TCP协议,而是构建在 QUIC之上,QUIC 在 UDP 上运行。所以也就自然没有了TCP的对头阻塞问题,及弱网传输问题。

QUIC 是构建在UDP协议之上的,主要增强功能如下:

传输层的多字节流

QUIC在传输层引入了多字节流的概念,可以针对每个流进行单独数据包丢失处理。这意味着QUIC流被视为独立实体,一个流的数据包丢失不会影响其他流。QUIC还为每个流实现了单独的流量控制,有效解决了传输层的队头阻塞问题。

连接迁移

在TCP协议之上,连接由4元组定义:客户端IP地址、客户端端口、服务器IP地址和服务器端口。如果这些参数中的任何一个发生变化,连接就会变为无效,需要连接重建。QUIC引入了一个称为连接ID的概念。为每个QUIC连接分配一个唯一的连接ID,可以识别两个对等方之间的连接。连接ID在QUIC传输层内部定义,在网络发生变化的情况下,也可以恢复连接。

灵活的拥塞控制

TCP采用严格的拥塞控制机制,很难调整,QUIC的拥塞控制算法被设计在用户态实现,可以更好的变更,有着更好的适应性。

内置加密

QUIC 默认集成了传输层安全性TLS1.3,确保了安全连接,无需单独进行 TLS 握手。这降低了延迟,提高了连接建立时间。

减少头部阻塞

与 TCP 不同,QUIC 是以流级别处理数据包丢失。这意味着单个数据包的丢失不会阻塞整个连接,进一步减少了首部阻塞问题。

0-RTT 连接建立

基于TLS1.3,HTTP/3可以实现 0-RTT的连接建立,这可以显著降低连接延迟。

HTTP/3的问题

HTTP/3构建在UDP之上,在当前网络基础设施上,UDP协议的支持尚不是很完善。

HTTP/1 vs HTTP/2 vs HTTP/3该如何抉择

HTTP/1.1的支持最为广泛,HTTP/2和HTTP/3提供了更好的性能,提供了如多路复用、头部压缩和安全性改进。

HTTP/2已被广泛采用,浏览器及Web服务器也都支持。HTTP/2和HTTP/3都设计为与HTTP/1.1向后兼容,HTTP 1.1迁移到HTTP/2相对来说比较轻松,因为两者都基于TCP协议。

从HTTP/2迁移到HTTP/3需要采用UDP协议,支持TLS 1.3,当前客户端与服务端也并不是完全支持。当前网络基础设施中对UDP协议的支持仍不是很完善。


http://www.kler.cn/news/363983.html

相关文章:

  • 背景动态变化的html页面
  • 【python实战】利用代理ip爬取Alibaba海外版数据
  • 苍穹外卖05
  • vuetify页面布局
  • elementui 的 table 组件回显已选数据时候使用toggleRowSelection 方法的坑点
  • Chainlit集成LlamaIndex和Chromadb实现RAG增强生成对话AI应用
  • 【uniapp版即时通讯】IM社交交友聊天语音视频通话双端APP+搭建视频教程
  • 028.爬虫专用浏览器-抓取#shadowRoot(closed)下的内容
  • C#与C++交互开发系列(九):字符串传递的几种形式
  • 执行Django项目的数据库迁移命令时报错:(1050, “Table ‘django_session‘ already exists“);如何破?
  • 【spring cloud】深入探讨 集群,分布式,微服务
  • OpenGL 进阶系列05 - OpenGL 图元重启(primitiverestart)
  • python的散列类型与字符编码
  • 为什么说Tcp是面向字节流的以及(Tcp粘包问题、TCP/UDP对比、listen函数的backlog参数的意义)
  • Kafka高可用性原理深度解析
  • 信息安全工程师(69)数字水印技术与应用
  • k8s-service详解
  • 使用python,自动实现将多个 JPG 文件转换为一个 PDF 文件
  • 11106 操作(c)
  • 【动态规划】子序列问题(上)
  • yarn的安装与使用以及与npm的区别(安装过程中可能会遇到的问题)
  • 动态规划-动归基础
  • 基于neo4j的新冠治疗和新冠患者轨迹的知识图谱问答系统
  • Hallo2 长视频和高分辨率的音频驱动的肖像图像动画 (数字人技术)
  • k8s 配置私有镜像仓库认证
  • repo将每个仓库回退到第一个commit的状态