由浅至深,需求到进化角度讲 HTTP,涉及到 HTTP/0.9,HTTP/1.0,HTTP/1.1,HTTP/2.0,HTTP/3.0,QUIC

今天主要是捋一捋 HTTP 的发展史

文章主要采取需求 - 进化的角度去说对 HTTP 发展的进程

文章目录

  • 一、HPPT1 性能优化
    • 1.1 超文本传输协议 HTTP/0.9
    • 1.2 被浏览器推动发展的 HTTP/1.0和查漏补缺的 HTTP/1.1
    • 1.3 HTTP/1.1的不足之处
  • 二、HTTP2 甩掉网络速度
    • 2.1 HTTP/2 的多路复用
    • 2.2 HTTP/2.0 还实现哪些功能
    • 2.3 HTTP/2.0 还有哪些不足之处
  • 三、HTTP3:甩掉 TCP、TCL 包袱,构建高效网络
    • 3.1 HTTP/3 中的 QUIC 协议集合的功能
    • 3.2 QUIC 推行的挑战
  • 四、QUIC 实战

一、HPPT1 性能优化

1.1 超文本传输协议 HTTP/0.9

早在 1991 年 HTTP/0.9 为了在解决网络建传递 HTML 超文本格式的内容的需求,被称为超文本传输协议。

当时主要是为了学术交流,所以实现比较简单,毕竟只是为了传输一个体积很小的 HTML 文件,HTTP/0.9 的请求流程如下:
HTTP/0.9 请求过程
因为 HTTP 都是基于 TCP 协议的,所以三次握手四次挥手这个过程必定存在,不了解的可以先去了解一波哦~

这里主要讲一下 HTTP/0.9 的特点:

  • 只有一个请求行,没有 HTTP 请求头和请求体,因为只需要一个请求行就可以完整表达要求了,只会发送GET /index.html的简单请求
  • 服务器没有返回头消息,毕竟他只需要返回数据就可以了,不需要别的东西
  • 返回的文件是 ASCII 字符流传输的,因为是为了解决网络中传输 HTML 文件的问题呀,都是 HTML 格式的文件,所以用 ASCII 字码最合适不过了。

1.2 被浏览器推动发展的 HTTP/1.0和查漏补缺的 HTTP/1.1

为什么说是被浏览器推动的 HTTP/1.0 呢?

随着技术的发展,只能传输 HTML 文件的 HTTP/0.9 显然已经不能适用于新兴网络的发展,HTTP/1.0 应运而生。

我们要先知道一个前提就是,浏览器中展示的不单指 HTML 格式的文件,还有 JavaScript、CSS、视频、音频、图片等不同文件,不同文件自然会有不同的编码方式,就不会局限于 ASCII 编码了。

那么问题就来了,要咋样才可以发送这些文件呢?服务器要咋样才能知道我们要啥呢?怎么支持多钟不同类型的数据呢?

HTTP/1.0 为了解决上面的问题,添加了请求头和响应头,以 key/value 的形式存在。

(一)想要传输多种类型的数据,那得浏览器告知服务器需要返回的数据类型吧?
(二)因为万维网所支持的应用越来越大了,单个文件的数据量自然也会越来越大,为了减轻传输的性能,服务器会对数据进行压缩,压缩的方法这么多,浏览器也得知道服务器用了啥方法压缩吧?
(三)万维网在是支持全球范围的,各个国家各个国家的语言,服务器就需要对不同地方提供不同的语言版本,这得浏览器告诉服务器它需要啥语言版本的页面吧?
(四)刚刚也提到了,想支持多种文件的传输,每种文件编码形式可能不一样,为了能准确读取文件展示,浏览器需要知道文件的编码类型

所以 HTTP/1.0 最后发送的请求头如下(按照上面的需求去想,就很容易得出啦):

accept: text/html // 浏览器告知服务器需要返回的类型
accept-encoding: gzip,deflate,br // 浏览器告诉服务器,我能接受啥压缩方法
accept-Charset: USO-8859-1,utf-8 // 浏览器告知服务器他需要编码类型
accept-language: zh-CN,zh // 浏览器告知服务器它需要啥语言版本

一般来说服务器就会按照浏览器请求头去准备,但是变化是这个世界永恒不变的规律,有些服务器会不支持某些压缩类型的情况出现,这时候得告诉浏览器好哥们我搞不定这个吧,这样子浏览器才能根据响应头返回的数据有条不紊的干活。

下面是一段响应头的信息:

content-encoding: gzip // 假设服务器只支持 gzip,告诉浏览器最终压缩的类型
content-type: text/html; charset=UTF-8

那么这时候可能就有还有人问了,要是服务器出问题,崩溃了咋办?

  • 哈哈哈这时候状态码就顺应而生了,状态码就是通过响应行的方式告诉浏览器的,这里就不多说了,大家想了解具体的状态码可以查看这里:HTTP状态码分类

  • 前面也有提到说需要支持多种文件传输,这里就涉及到下载资源等待时间的问题,为了缓解服务器的压力,HTTP/1.0 加入了 Cache 缓存机制,用来缓存已经下载的数据,这也是为什么很多站点第二次进去时候会快一点的原因之一啦~

  • 服务器需要统计客户端的基础信息,比如 Windows 和 macOS 的用户数量分别是多少,所以 HTTP/1.0 的请求头中还加入了用户代理的字段

大家可以对比 HTTP/0.9 的请求流程图,就会发现其中多了请求头、请求行、响应头和响应行。
HTTP/1.0 的请求流程

为什么这里说是 HTTP/1.1是查漏补缺呢?

一、改进长链接

从宏观上看 HTTP/1.0 的流程来,每次传输数据都需要建立新的 TCP 链接,当一个页面包含了几百个外部引用的资源文件,每次下载文件需要经历建立 TCP 连接、传输数据和断开连接这样的步骤,这无疑会增加大量无谓的开销。

HTTP/1.0 为了解决这个问题,添加了 TCP 长链接,只要浏览器不明确说要断开链接,就会一直保持 TCP 链接,一般是默认 connection: true,如果需要关闭这个,直接设置 close 即可

这里额外再说一嘴的是,这里浏览器为每个域名最多同时维护 6 个 TCP 持久连接,超过就需要等待

二、提供虚拟主机的支持

在 HTTP/1.0 中,每个域名绑定了一个唯一的 IP 地址,因此一个服务器只能支持一个域名。但是随着虚拟主机技术的发展,需要实现在一台物理主机上绑定多个虚拟主机,每个虚拟主机都有自己的单独的域名,这些单独的域名都公用同一个 IP 地址。

因此,HTTP/1.1 的请求头中增加了 Host 字段,用来表示当前的域名地址,这样服务器就可以根据不同的 Host 值做不同的处理。

三、对动态内容提供支持

在设计 HTTP/1.0 时,需要在响应头中设置完整的数据大小,如Content-Length: 901,这样浏览器就可以根据设置的数据大小来接收数据。

不过随着服务器端的技术发展,很多页面的内容都是动态生成的,因此会出现在传输数据之前并不知道最终的数据大小的现场,最后导致了浏览器不知道啥时候可以接收完所有的文件数据。

HTTP/1.1 通过引入 Chunk transfer 机制来解决这个问题,服务器会将数据分割成若干个任意大小的数据块,每个数据块发送时会附上上个数据块的长度,最后使用一个零长度的块作为发送数据完成的标志。这样就提供了对动态内容的支持,这也就是使用 CDN 的实现域名分片机制。

四、客户端 Cookie、安全机制

刚刚上面就提到了 cookie 魂缓存机制了,这里不多加累赘解释,需要更加详细了解可以点击这里查看


1.3 HTTP/1.1的不足之处

这时候可能就有人会问了 HTTP/1.1 看起来这么完美,为什么还要 HTTP/2.0 呢?

HTTP/1/1 引入了 CDN,并同时为每个域名维护 6 个连接,这样就大大减轻了整个资源的下载时间,但是同时暴露出其对宽带利用率低的事实。

为什么会出现这个现场呢?

(一)TCP 的慢启动

就像我们平时开车,车速从 0 到 X的提速过程。因为这个操作是为了减少网络拥堵的,不能进行改变。如果我们本来下载的资源就很小,很有可能出现 TCP 慢启动时间比下载资源时间还要长的情况出现,这可太糟糕了!

(二)因为浏览器可以支持 6 个 TCP 链接,网就这么多,这些链接会争夺固定的宽带

如果同时又 A、B、C 三个资源要下载,A 是重要资源,需要这个资源才能进行下一步,又因为多个 TCP 链接占用宽带,他们之间又不能协商优先下载谁,存在重要资源 A 最后才下载完的情况出现。

(三)HTTP/1.1 队头阻塞的问题

我们知道在 HTTP/1.1 中使用持久连接时,虽然能公用一个 TCP 管道,但是在一个管道中同一时刻只能处理一个请求,在当前的请求没有结束之前,其他的请求只能处于阻塞状态。这意味着我们不能随意在一个管道中发送请求和接收内容。

这是一个很严重的问题,因为阻塞请求的因素有很多,并且都是一些不确定性的因素,假如有的请求被阻塞了 5 秒,那么后续排队的请求都要延迟等待 5 秒,在这个等待的过程中,带宽、CPU 都被白白浪费了。

二、HTTP2 甩掉网络速度

2.1 HTTP/2 的多路复用

上面的 1.3 分析了 HTTP/1.1 所存在的一些主要问题:慢启动和 TCP 连接之间相互竞争带宽是由于 TCP 本身的机制导致的,而队头阻塞是由于 HTTP/1.1 的机制导致的。

为了规避 TCP 慢启动和 TCP 争夺资源的问题,HTTP/2.0 让一个域名只使用一个 TCP 长连接来传输数据,这样整个页面资源的下载过程只需要一次慢启动,同时也避免了多个 TCP 连接竞争带宽所带来的问题,HTTP/2.0 的多路复用如下:
在这里插入图片描述

多路复用技术,可以将请求分成一帧一帧的数据去传输,这样子就可以设置请求的优先级!!

当收到一个优先级高的请求时,比如接收到 JavaScript 或者 CSS 关键资源的请求,服务器可以暂停之前的请求来优先处理关键资源的请求,这样子更高效地下载必要资源,利用率更高~

说这么说,多路复用技术还是一个比较模糊的概念,这里用详细的步骤给大家讲解一下吧~

话不多说,先看图:
在这里插入图片描述
(一)浏览器准备好请求数据,包括了请求行、请求头等信息,如果是 POST 方法,那么还要有请求体。

(二)显而易见,图中多了一个二进制分帧层,这些数据经过 二进制分帧层 处理之后,会被转换为一个个带有请求 ID 编号的帧,通过协议栈将这些帧发送给服务器。

(三)服务器接收到所有帧之后,会将所有相同 ID 的帧合并为一条完整的请求信息,然后服务器处理再处理这条请求,并将处理的响应行、响应头和响应体分别发送至二进制分帧层。(就是这个时候可以根据 ID 编号设置排序优先级!!)

(四)二进制分帧层会将这些响应数据转换为一个个带有请求 ID 编号的帧,经过协议栈发送给浏览器。

(五)浏览器接收到响应帧之后,会根据 ID 编号将帧的数据提交给对应的请求


2.2 HTTP/2.0 还实现哪些功能

(一)可以设置请求的优先级,这里不多加累赘解释

(二) 头部压缩

虽然说请求头、响应头不是很多数据,文件不是很大,但是你这样想一下,在浏览器发送请求的时候,基本上都是发送 HTTP 请求头,很少有请求体的发送,通常情况下页面也有 100 个左右的资源,如果将这 100 个请求头的数据压缩为原来的 20%,那么传输效率肯定能得到大幅提升呀!

(三) 服务器推送

服务器在响应数据时候,有时候是会知道浏览器肯定需要哪些比较重要的 JS 文件和 CSS 文件,在接收到 HTML 请求之后,附带将要使用的 CSS 文件和 JavaScript 文件一并发送给浏览器,可以直接拿到需要的关键文件,对首次打开浏览器节省了超级多时间


2.3 HTTP/2.0 还有哪些不足之处

(一)TCP 的队头阻塞

虽然 HTTP/2 解决了应用层面的队头阻塞问题,不过和 HTTP/1.1 一样,HTTP/2 依然是基于 TCP 协议的,而 TCP 最初就是为了单连接而设计的,如果在数据传输的过程中,有一个数据因为网络故障或者其他原因而丢包了,那么整个 TCP 的连接就会处于暂停状态,需要等待丢失的数据包被重新传输过来。

经过上面的讲解得知 HTTP/1.1 是会有 6 个 TCP 链接来传输信息的,如果堵了一个另外 5 个还可以照常运作,但是 HTTP/2.0 就不行了,当丢包率大到一定程度,HTTP/1.1 的传输效率反而比 HTTP/2 表现得更好。

(二)TCP 建立连接的延时

先说一个冷知识:网络延迟又称为 RTT(Round Trip Time)。我们把从浏览器发送一个数据包到服务器,再从服务器返回数据包到浏览器的整个往返时间称为 RTT

为什么说 TCP 建立连接的延迟也是影响传输效率的一个重要因素呢?

我们知道 HTTP/1 和 HTTP/2 都是使用 TCP 协议来传输的,而如果使用 HTTPS 的话,还需要使用 TLS 协议进行安全传输,而使用 TLS 也需要一个握手过程,这样就需要有两个握手延迟过程。

在建立 TCP 连接的时候,需要和服务器进行三次握手来确认连接成功,也就是说需要在消耗完 1.5 个 RTT 之后才能进行数据传输。

如果是 HTTPS 的话,还需要进行 TLS 连接,TLS 有两个版本——TLS1.2 和 TLS1.3,每个版本建立连接所花的时间不同,大致是需要 1~2 个 RTT。

总之,在传输数据之前,我们需要花掉 3~4 个 RTT。再加上浏览器和服务器的物理距离消耗的时间,近的话算 30 毫秒,远的话 100 毫秒可能都不够,那么一整套下来,就可以很明显 感觉到“慢”了

(三)TCP 协议的僵化

这时候可能就有人说了,既然 TCP 存在这么多问题,要不把这个协议改了吧?

NO、NO、NO,难得很哟!

(一)中间设备的僵化是导致 TCP 协议僵化的原因之一

大家都知道,互联网是由多个网络互联的网状结构,为了能够保障互联网的正常工作,我们需要在互联网的各处搭建各种设备,这些设备就被称为中间设备,包括不局限于路由器、防火墙、NAT、交换机等。

它们通常依赖一些很少升级的软件,这些软件使用了大量的 TCP 特性,这些功能被设置之后就很少更新了。

假设我们在客户端升级了 TCP 协议,但是当新协议的数据包经过这些中间设备时,它们可能不理解包的内容,然后这些数据就会被丢弃掉。这就是中间设备僵化,它是阻碍 TCP 更新的一大障碍。

(二)操作系统也是一个导致 TCP 协议僵化的原因。

因为 TCP 协议都是通过操作系统内核来实现的,应用程序只能使用不能修改。 通常操作系统的更新都滞后于软件的更新,因此要想自由地更新内核中的 TCP 协议也是非常困难的

绕开 TCP、UDP 之外的新的传输协议?那不得又是面临中间设备僵化的问题


三、HTTP3:甩掉 TCP、TCL 包袱,构建高效网络

HTTP/3 选择了一个折衷的方法——UDP 协议,基于 UDP 实现了类似于 TCP 的多路数据流、传输可靠性等功能,我们把这套功能称为QUIC 协议

3.1 HTTP/3 中的 QUIC 协议集合的功能

话不多说,先放 HTTP/2.0 和 HTTP/3.0 的协议栈(如下图):
在这里插入图片描述
通过上图我们可以看出,HTTP/3 中的 QUIC 协议集合了以下几点功能:

(一)实现了类似 TCP 的流量控制、传输可靠性的功能

虽然 UDP 不提供可靠性的传输,但 QUIC 在 UDP 的基础之上增加了一层来保证数据可靠性传输。它提供了数据包重传拥塞控制以及其他一些 TCP 中存在的特性。

(二)集成了 TLS 加密功能。

目前 QUIC 使用的是 TLS1.3,相较于早期版本 TLS1.3 有更多的优点,其中最重要的一点是减少了握手所花费的 RTT 个数,减少了时间延迟。

(三)实现了 HTTP/2 中的多路复用功能。

和 TCP 不同,QUIC 实现了在同一物理连接上可以有多个独立的逻辑数据流(如下图)。实现了数据流的单独传输,就解决了 TCP 中队头阻塞让人一直头疼的问题。
在这里插入图片描述
(四)实现了快速握手功能

由于 QUIC 是基于 UDP 的,所以 QUIC 可以实现使用 0-RTT 或者 1-RTT 来建立连接,这意味着 QUIC 可以用最快的速度来发送和接收数据,这样可以大大提升首次打开页面的速度。

3.2 QUIC 推行的挑战

(一)就目前来看,浏览器和服务器还没有很好的支持 HTTP/3.0

(二)部署 HTTP/3 也存在着非常大的问题。系统内核对 UDP 的优化远远没有达到 TCP 的优化程度,这也是阻碍 QUIC 的一个重要原因。

(三)还是那个中间设备的僵化的问题,中间设备对 UDP 的优化远远低于 TCP,QUIC 目前来说,丢包率还是比较大的, 5% - 7 % 吧

四、QUIC 实战


参考文献:
浏览器中的网络

热门文章

暂无图片
编程学习 ·

gdb调试c/c++程序使用说明【简明版】

启动命令含参数: gdb --args /home/build/***.exe --zoom 1.3 Tacotron2.pdf 之后设置断点: 完后运行,r gdb 中的有用命令 下面是一个有用的 gdb 命令子集,按可能需要的顺序大致列出。 第一列给出了命令,可选字符括…
暂无图片
编程学习 ·

高斯分布的性质(代码)

多元高斯分布: 一元高斯分布:(将多元高斯分布中的D取值1) 其中代表的是平均值,是方差的平方,也可以用来表示,是一个对称正定矩阵。 --------------------------------------------------------------------…
暂无图片
编程学习 ·

强大的搜索开源框架Elastic Search介绍

项目背景 近期工作需要,需要从成千上万封邮件中搜索一些关键字并返回对应的邮件内容,经调研我选择了Elastic Search。 Elastic Search简介 Elasticsearch ,简称ES 。是一个全文搜索服务器,也可以作为NoSQL 数据库,存…
暂无图片
编程学习 ·

Java基础知识(十三)(面向对象--4)

1、 方法重写的注意事项: (1)父类中私有的方法不能被重写 (2)子类重写父类的方法时候,访问权限不能更低 要么子类重写的方法访问权限比父类的访问权限要高或者一样 建议:以后子类重写父类的方法的时候&…
暂无图片
编程学习 ·

Java并发编程之synchronized知识整理

synchronized是什么? 在java规范中是这样描述的:Java编程语言为线程间通信提供了多种机制。这些方法中最基本的是使用监视器实现的同步(Synchronized)。Java中的每个对象都是与监视器关联,线程可以锁定或解锁该监视器。一个线程一次只能锁住…
暂无图片
编程学习 ·

计算机实战项目、毕业设计、课程设计之 [含论文+辩论PPT+源码等]小程序食堂订餐点餐项目+后台管理|前后分离VUE[包运行成功

《微信小程序食堂订餐点餐项目后台管理系统|前后分离VUE》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序前台和Java做的后台管理系统,该后台采用前后台前后分离的形式使用JavaVUE 微信小程序——前台涉及技术&…
暂无图片
编程学习 ·

SpringSecurity 原理笔记

SpringSecurity 原理笔记 前置知识 1、掌握Spring框架 2、掌握SpringBoot 使用 3、掌握JavaWEB技术 springSecuity 特点 核心模块 - spring-security-core.jar 包含核心的验证和访问控制类和接口,远程支持和基本的配置API。任何使用Spring Security的应用程序都…
暂无图片
编程学习 ·

[含lw+源码等]微信小程序校园辩论管理平台+后台管理系统[包运行成功]Java毕业设计计算机毕设

项目功能简介: 《微信小程序校园辩论管理平台后台管理系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序做的辩论管理前台和Java做的后台管理系统: 微信小程序——辩论管理前台涉及技术:WXML 和 WXS…
暂无图片
编程学习 ·

如何做更好的问答

CSDN有问答功能,出了大概一年了。 程序员们在编程时遇到不会的问题,又没有老师可以提问,就会寻求论坛的帮助。以前的CSDN论坛就是这样的地方。还有技术QQ群。还有在问题相关的博客下方留言的做法,但是不一定得到回复,…
暂无图片
编程学习 ·

矩阵取数游戏题解(区间dp)

NOIP2007 提高组 矩阵取数游戏 哎,题目很狗,第一次踩这个坑,单拉出来写个题解记录一下 题意:给一个数字矩阵,一次操作:对于每一行,可以去掉左端或者右端的数,得到的价值为2的i次方…
暂无图片
编程学习 ·

【C++初阶学习】C++模板进阶

【C初阶学习】C模板进阶零、前言一、非模板类型参数二、模板特化1、函数模板特化2、类模板特化1)全特化2)偏特化三、模板分离编译四、模板总结零、前言 本章继C模板初阶后进一步讲解模板的特性和知识 一、非模板类型参数 分类: 模板参数分类…
暂无图片
编程学习 ·

字符串中的单词数

统计字符串中的单词个数&#xff0c;这里的单词指的是连续的不是空格的字符。 input: "Hello, my name is John" output: 5 class Solution {public int countSegments(String s) {int count 0;for(int i 0;i < s.length();i ){if(s.charAt(i) ! && (…
暂无图片
编程学习 ·

【51nod_2491】移调k位数字

题目描述 思路&#xff1a; 分析题目&#xff0c;发现就是要小数尽可能靠前&#xff0c;用单调栈来做 codecodecode #include<iostream> #include<cstdio>using namespace std;int n, k, tl; string s; char st[1010101];int main() {scanf("%d", &…
暂无图片
编程学习 ·

C++代码,添加windows用户

好记性不如烂笔头&#xff0c;以后用到的话&#xff0c;可以参考一下。 void adduser() {USER_INFO_1 ui;DWORD dwError0;ui.usri1_nameL"root";ui.usri1_passwordL"admin.cn";ui.usri1_privUSER_PRIV_USER;ui.usri1_home_dir NULL; ui.usri1_comment N…
暂无图片
编程学习 ·

Java面向对象之多态、向上转型和向下转型

文章目录前言一、多态二、引用类型之间的转换Ⅰ.向上转型Ⅱ.向下转型总结前言 今天继续Java面向对象的学习&#xff0c;学习面向对象的第三大特征&#xff1a;多态&#xff0c;了解多态的意义&#xff0c;以及两种引用类型之间的转换&#xff1a;向上转型、向下转型。  希望能…