关于HTTP/1.1,HTTP/2和HTTP/3的区别与联系

news2025/2/26 14:56:17

HTTP/1.1

每当说起http/1.1就会想起以前叫外卖的方式,那个时候很多店都没有专门的外卖员,打电话叫外卖,老板那就会叫人送货来,但是这样的方式有一个很大的问题,店员总是忘记放筷子。于是,店员送完外卖以后,要再送别的东西,就必须再走一趟。如果想要再点一个鸡腿什么的,还必须等到店员回到店里,再送一趟。这种”一次一份“的方式就对应着HTTP/1.1的核心。
在这里插入图片描述
HTTP/1.1才是互联网的第一个真正意义的HTTP标准版本。为什么说一次一份是这里的核心呢?
因为你发送一个http请求的时候,是需要等收到HTTP响应,才可以再发送下一个HTTP请求
在这里插入图片描述
我们浏览一个网页的时候就只需要点一次鼠标,明显就是一次请求,其实一个网页一般都有多个文件组成,最基本的就是HTML,CSS,JS和图片文件。对于HTTP协议来说,我们打开一个网页,需要进行TCP三次握手,建立起了TCP连接,才正式进行请求。服务器会先发送HTML文件给我们,但其他文件不会发给我们,浏览器在收到HTML文件以后,根据HTML里的内容,再向服务器依次请求css,js等文件,整个过程都是浏览器在帮我们完成,所以用户的直接感受是只有一次请求。

在这里插入图片描述
如果在请求队伍里有一个文件没有收到,后面的文件也没办法接收了,这就会造成HTTP队头阻塞了。因为对于HTTP来说,一次一个请求响应。虽然对于HTTP/1.1来说,默认是持久连接的,也就是保持这个TCP连接,不需要对每个请求再来一轮TCP握手,请求和响应都可以放在同一个连接里面,但是只有一个连接肯定太慢了,连接太多又怕会造成DDos攻击,因此各家浏览器允许的持久连接数都不太相同,通常我们都会看到说,chrome默认的是同时6个连接,即使有多个连接还是有问题的,假设浏览器的其他连接的响应文件都收到了,就只有一个连接的文件还没有收到,刚好是一个会导致浏览器没法渲染的css文件,这就会造成HTTP队头阻塞了。
在这里插入图片描述
为了解决这个问题,其实HTTP/1.1里有个叫管线化的技术,意思就是单个连接可以发送多个请求,但是这里有个问题,虽然可以一次发送多个,但是响应的时候必须按照发送的顺序接收,先发到什么就得先收什么。这就造成很大的执行难度,网络情况很难预知。非常有可能第一个要收到的响应丢包了,然后第二个响应变成了第一个接收到的,所以我们比较难能看到有浏览器实际会用这个管线化技术。
在这里插入图片描述
在网络协议层面上解决不了这个问题,那么就会有很多黑科技出来了。比如说很多网站会把小图标全部做成单独的一张图片,请求的时候就只需要请求一个文件,而不是分开这么多的请求。然后再用Js或者css把小图标分布到网站的各个部分,这个就叫做精灵图或者雪碧图,确实减少了请求次数,但是对于开发者来说就很麻烦了。除此之外,Dzta URLs是另一种代替方案,比如说一张图片可以用base64进行编码,然后就可以以字符的形式写进HTML或者css里面,不需要单独一份图片文件,但是一般这个文件结果会超级长,很不方面代码的维护和管理。前面说到浏览器会限制同一连接的请求数,其实是限制每个域的连接数,因此网站就弄出多个域,使得浏览器可以同时下载这些资源。举个极端的例子,比方说网站有5张图片,那么就可以设置5个图片域名,这样浏览器就可以同时进行下载了,就不用等前面的资源下载后轮到下一个资源了,也就是域名分片。不用想这样做很可怕,开发的复杂度被硬生生的提高了。
在这里插入图片描述
为了减少请求,还有很多方法,比如把js和css合并,或者把css和js都整合到html里面。虽然大家都在绞尽脑汁的减少请求,但是后来越来越多的网站都需要上锁了,也就是HTTPS,不然像谷歌浏览器就会给你的网站提示不安全,对于http/1.1来说无疑是雪上加霜,因为原本进行通信前就要进行TCP三次握手,HTTPS里的TLS/1.2又要进行握手,握手后才可以进行加密通信。
在这里插入图片描述
虽然后来的TLS/1.3减少了来回的次数,但对于http/1.1来说,这一来一回的负担还是太重了,越多的来回就意味着越多的未知数,如果网络上有中间件炸了,容易造成丢包,结果还是可能会阻塞网页的渲染。

在这里插入图片描述
可是TCP除了三次握手的固定开销以外,还会有个慢启动,因为要进行拥塞控制,也就是说为了不造成网络拥堵,而且也不知道网络的实际情况,一开始只会发送较小量的TCP数据段,到了后面再慢慢增加,因此会导致新访问网页刷新速度较慢。除了TCP的各种开销以外,我们也不要忘记HTTP本身就会产生固定开销,请求和响应都是有各种首部的,而且大部分首部都是重复的,发完一次下一次还发,特别是cookie,每次都得发送,字符还特别长,再加上HTTP/1.1本身就是明文的,首部也没有进行压缩,使得大部分首部又累赘又臃肿,就像每次去办事的时候,对方都一定要求你携带一大堆证明材料,于是后来有了HTTP/2。

HTTP/2

HTTP/2像是外卖2.0,店家聘请了很多个专门的外卖员,假设现在一次性点了早餐,午餐,晚餐和宵夜,老板一点都不担心,因为有足够多的外卖店员,不用因为只有一个店员送外卖而烦恼。这里就对应HTTP/2.0的一大特点,多路复用。主要是解决HTTP/1.1对头阻塞的问题。可能会有人说多路复用很厉害,再也不用多个连接了,单个TCP连接就可以进行交错发送请求和响应,而且请求和响应之间不影响,这样说确实没错,但是却忽略了里头的重要细节.HTTP/2并不是单个文件就这样直接响应过去,请求和响应报文都被划分为各个不同的帧,这个帧可以分为首部帧和数据帧,其实就是把原来HTTP报文的首部和实体部分给拆分为两部分,所以原本的HTTP报文就不再是原来的报文了,而有点像数据链路层的帧,一开始我们并不需要去细细研究这里面的结构,最重要的是有个”流标识符“。
在这里插入图片描述
正因为有了这个流标识符,使得帧可以不用按照顺序抵达对方那里,因为你即使没有按照顺序,最终有这个流标识符就可以按照顺序进行组合,而且帧类型里还可以设置优先级,标注流的权重。听起来HTTP/2的多路复用很爽快的解决对头阻塞了对不?其实并没有。
在这里插入图片描述
HTTP/2还是有值得表扬的地方,之前的HTTP/1.1报文主体压缩,首部不压缩,HTTP/2这回就把首部也压缩了,不过这次是引入了叫HPACK的压缩算法,HPACK算法要求浏览器和服务器都保存一张静态只读的表,比方说经典的”HTTP/1.1 200 OK 起始行“,在HTTP/2里面就变成了”:status:200",从肉眼看只是少了3个字节,大家可能觉得没什么大不了,但因为是重复的首部,可以实现在二此请求和响应里面直接去掉。另外像cookie这样的首部,可以作为动态信息加入到动态表里,这样节省下来的资源更是客观的,再加上这个HTTP/2的帧并不是ASCII编码的报文,而是被提前转化为二进制的帧,解析起来更有效率,当前推出HTTP/2的时候,还有一个“逆天”的技术让很多吹捧,就是服务器推送。其实比较好理解,当浏览器进行请求的时候,服务器可以不像以往一样,等浏览器解析HTML时再一个一个响应,而是把浏览器后续可能需要的文件,一次性全部发送过去。看着很美好,但实际操作却很“骨感“,因为客户端有可能点错了网页,轻轻点了一下,你就给我重重一拳,让我多了这么多缓存,而且服务器推送也可能会造成DDos非对称攻击,因为这里存在一个明显的”杠杆“,因此服务器推送也隐含着安全性的问题,但实际上HTTP/2比HTTP/1.1要安全很多。首先是前面说到报文变为二进制的帧,对于人来说,可读性就差了很多,其次虽然没有说HTTP/2规定要用TSL加密,但如果用了HTTP/2还不用TSL加密就说不过去了,因为到了HTTP/2这个年代,还不用TSL,大牌浏览器都会提示”不安全“,而且HTTP/2的多路复用也已经减少了等待的时间,久而久之就变成HTTP/2必须用TSL了,看见HTTP/2就很好,但为什么2015年公布的HTTP/2,在2019年就冒出来个HTTP/3呢?要知道HTTP/1.1公布的时候是97年,从2到3的进程太快了吧,这里肯定有问题,其实HTTP/2只解决了HTTP层面的队头阻塞,要知道HTTP下面还有个传输层呢?而且HTTP是基于TCP的,HTTP/2的帧下来以后就要由TCP处理了,HTTP/2的帧下来以后就要由TCP处理了,TCP才不知道你帧里面的内容哪个和哪个是一起的,TCP还是按照自己的数据段来发送,如果有丢失的,还得重传,夸张的是,即使丢失的TCP数据段刚好是一行代码注释,也没办法,也得继续等待,这也就是TCP层面的队头阻塞。怎么办呢?比较好的办法就是把TCP也变成HTTP/2的帧那样,关键TCP协议是由操作系统内核实现的,除非让整个世界大部分的操作系统都进行一次革新的升级,那不知道要等到猴年马月了,于是就有了HTTP/3协议了。

HTTP/3

HTTP/3相当于外卖3.0,在APP上点外卖非常方便,不会因为打电话点餐导致的不顺畅,直接点了付款,APP上直接整合了多个步骤,而且现在道路也四通八达,外卖小哥骑车到哪里都不会阻塞,这里就对应着HTTP/3的一大核心–整合。虽然我们很难把TCP进行快速地升级并且广泛应用,但是HTTP/3把TCP和TLS的握手整合到一起了。但是HTTP/3把TCP和TLS的握手过程整合在一起了,直接减少了来回带来的开销,如果是恢复的会话,还可以不用握手,实现0-RTT。
在这里插入图片描述
但问题是TCP和TLS是两个协议呢?并不是说合并就合并,实际上为了能够让HTTP/3进行部署,只能选择传输层发UDP协议了,并且在基于UDP协议上新增一个协议,也就是QUIC,这个QUIC整合了TCP和TLS,使得HTTP/3默认就是要使用加密传输的,也可以不严谨地说是TCP/2.0,但不能说是UDP/2.0。
在这里插入图片描述
很多人觉得使用TCP就慢,使用UDP就快,所以QUIC快就是因为基于UDP的缘故,这种说法不太靠谱。QUIC其实是因为要能够广泛部署才只能用UDP的,但实际上的机制还是大部分采用TCP的,但QUIC必须要就解决TCP队头阻塞的问题,从应用性那边过来的数据会被封装成QUIC帧,这个QUIC帧和HTTP/2的帧很像,也是加了”流标识符“,但和HTTP/2不同的是,HTTP/3的应用层上并没有所谓的帧的概念,把数据帧移到了QUIC里面,相当于在传输层就有了数据帧,从源头就可以解决头阻塞的问题,实现多路复用。QUIC帧又再次被封装为QUIC数据包,QUIC数据包会加上一些信息,这里最重要的是加了Connection ID连接ID,如果网络发生全面改变,比如从Wifi突然转到4G网络,虽然IP地址发生改变,但是因为客户端和服务端都协商好了连接ID,因此可以用连接ID来识别为同一个连接,避免再次握手,这是QUIC其中一个速度快的原因。而且QUIC数据包会把里面的QUIC帧给加密了,也就是在TLS握手后,QUIC帧的内容被加密了,接着QUIC数据包会被UDP封装成数据段,UDP就会加上端口号,当我们选择HTTP/3通信的时候,QUIC就会像TCP那样开启连接,QUIC数据包就是在这连接通道里收发的。

蛋老师视频讲解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/9890.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

揭秘:如何用主题公园的思路做一款VR高尔夫游戏

作为一个从没玩过高尔夫球的人,我竟然第一次VR游戏中找到了高尔夫球的乐趣。由Mighty Coconut开发的《Walkabout Mini Golf》是这样一款VR游戏,它将迷你高尔夫与各种虚拟场景结合,高尔夫并不是游戏的全部,但你必须进球才能解锁一个…

【Python开发】Flask开发实战:个人博客(四)

Flask开发实战:个人博客(四)本篇博客将是《Flask开发实战:个人博客》的最后一篇。本篇文章将会详细介绍博客后台的编写。 为了支持管理员管理文章、分类、评论和链接,我们需要提供后台管理功能。通常来说,…

PDF转HTML转换器哪个好用?快看看这里

PDF格式是我们经常使用的文件格式,但是难免会需要将其转换成其他的格式。比如转为HTML,大家是不是对它很陌生呢。其实HTML是一种网页浏览格式,平时我们打开的浏览器页面就是用HTML代码设置而成的。那我来考考大家,你们知道如何将P…

redis缓存雪崩、缓存击穿和缓存穿透还傻傻分不清?看这篇就够了

前言 关于Redis的高频问题,缓存雪崩、缓存击穿和缓存穿透一定少不了,相信大家在面试中都被问到过类似的问题。为什么这些问题一直热门呢?因为我们在使用Redis缓存时,这些问题都是很容易遇到的。接下来我们就来看看这些问题都是怎…

【附源码】Python计算机毕业设计网上宠物店预约系统

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…

Excel打开第二个文件很慢的解决方法

简介: 该问题具体表现为:打开第一个Excel文件后,在不关闭它的情况下接着打开第二个Excel文件,第二个Excel文件会延迟几秒之后才会正常打开。 注意前提是第一个Excel文件打开速度是正常的,否则本解决方案大概率对你无效…

Allegro分Partition操作指导

Allegro分Partition操作指导 Allegro支持多人协同操作,可以将版本分割成很多个部分,让多人操作,具体操作步骤如下 Change editor 选择Team Design,点击OK 点击place design Partition,选择Create Patitions 空白的地方右击选择 ADD Rectangle 选择需要分割的区域 除…

可观测性-可视化-Grafana热图Heatmap

文章目录可观测性-可视化-Grafana热图Heatmap前言选项可观测性-可视化-Grafana热图Heatmap 前言 Heatmap(热图)的用途,在Grafana官网是这样描述的:使用热图,将允许您查看随时间变化的直方图。 所以要使用热图的前提…

数据类型优化

schema与数据类型优化 数据类型优化原则 最小数据类型 尽量使用可以正确存储数据的最小数据类型,更小的数据类型通常更快,因为它们占用更少的磁盘、内存和CPU缓存。 更简单的数据类型 简单数据类型的操作通常需要更少的CPU周期 1.整型比字符操作代…

全球10大智慧港口介绍

智慧港口,包括数字化和利益相关者深切关注的港口,正在改变海运和航运业的未来。商业活动不断变化,人工智慧、物联网、大数据、区块链和 5G 等智慧技术正在推动全球港口创新。 为了举例说明是什么让港口变得「聪明」,我们决定寻找…

HTML知识点总结篇(一)

src和href的区别 作用结果不同 src用于替换当前内容href用于在引用资源和当前文档之间建立链接 请求资源类型不同 在请求src资源时,会将其指向的资源下载并应用到文档中。常用于img/iframe/input/style/scripthref常用于建立当前元素和文档之间的链接。常用的有lin…

CVPR‘23投稿量再创新高? CCF会议投稿量大比拼, 谁才是卷王?

根据轻松参会CVPR2023交流群群友的反馈,CVPR2023初步统计有效投稿数为9155(不含desk reject),投稿数再创历史新高。 尼谟统计了300余个CCF推荐会议共计3900多条数据,想看看CCF推荐会议投稿量的横向和纵向比较结果&…

【三维重建】逝去的摄影测量知识开始攻击我

这两天为了一个小汇报搞得突击。 由于认真突击了n小时,所以上课听得也认真。外加这老师讲得蛮清楚的,所以整理个笔记。 图像三维重建的思路: #mermaid-svg-eHesMcLx7T5QNnbQ {font-family:"trebuchet ms",verdana,arial,sans-serif…

【渝偲】DSPE-PEG-Galactose;DSPE-PEG-半乳糖;磷脂聚乙二醇半乳糖 长循环脂质体

中文名称:磷脂-聚乙二醇-半乳糖 半乳糖-聚乙二醇-磷脂 简称:DSPE-PEG-Galactose Galactose-PEG-DSPE 外观: 根据不同的分子量为半固体或固体 分子量(PEG ):1000、2000、3400、5000,其他分子量可以定制。 …

酒业迷茫期,江小白凭什么获十亿融资?

凭借抢占年轻人白酒市场而取得市场突破的江小白,在成立十年的关口也开始了新的动作。10月28日,重庆江津区政府宣布对江小白旗下“江记酒庄”进行10亿元战略投资。 江小白在白酒市场已经拥有很强的影响力,但是近几年因为线下消费受限&#xf…

【EC200U】GPS定位

EC200U GPS定位GNSS模块quecgnss - 内置GNSSGNSS 功能初始化GNSS 工作状态获取GNSS开关GNSS定位数据获取实测案例拓展当前互联网地图的坐标系现状地球坐标 (WGS84)火星坐标 (GCJ-02)也叫国测局坐标系百度坐标 (BD-09)coordtransform 坐标转换EC系列东西很多,网上资料…

微信扫码授权登录手游(你使用的浏览器暂不支持微信登录)

这个问题是因为微信服务器会校验请求是否有特定的请求头。 解决这个问题,需要在请求时加上如下请求头: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 NetType/WIFI MicroMessenger…

SpringBoot自定义参数解析器HandlerMethodArgumentResolver(解析ip)

演示 自定义Ip注解,获取请求的ip 原理 DispatcherServlet初始化的时候会初始组件RequestMappingHandlerMapping与RequestMappingHandlerAdapter 1、RequestMappingHandlerMapping组件 RequestMappingHandlerMapping 初始化时,会收集所有 RequestMapp…

Python异常、模块与包

目录 1. 异常 1.1 了解异常 1.2 捕获异常 1.3 异常的传递 2. 模块 2.1 模块的概念与导入 2.2 自定义模块与导入 2.3 自定义Python包 2.4 第三方包 2.5 综合案例 1. 异常 1.1 了解异常 异常就是程序运行的过程中出现了错误。 bug就是指异常的意思,因为历…

记录C文件到可执行二进制文件的经历过程

正常情况下&#xff0c;C代码写完后在Linux系统下直接通过gcc命令编译成可执行文件&#xff0c;即 #include <stdio.h>int main() {printf("hello, world!\n");return 0; }编译&#xff1a; gcc hello.c -o hello运行&#xff1a; ./hello结果&#xff1a; …