HTTP/1.1、HTTPS、HTTP/2、HTTP/3 的区别和发展过程

HTTP

HTTP(Hypertext Transfer Protocol,超文本传输协议)是一种用于传输超文本数据(例如 HTML 文档、图像、音频、视频等)的应用层协议。它是互联网上数据传输的基础,被用于客户端(例如浏览器)和服务器之间的通信。

1.HTTP1.1

1.明文形式传输,安全性较低。

2.可以做到长连接,使用一次TCP请求来处理多个HTTP请求,实现连接的复用。

3.串行传输(处理下一请求之前必须先返回上一个请求)导致的对头阻塞问题。(默认不开启管道模式)

队头阻塞问题:因为一个请求处理时间很长导致后面的请求不断堆积越来越多。

HTTP1.1 的优化方法

1.合并请求

HTTP1.1默认是不开启管道模型的,所以第一个发送的请求没有收到响应第二个请求就不会发送出去。类似于阻塞IO的串行执行。所以浏览器一般会同时开启5-6个请求,每一个请求使用不同的TCP连接,这就导致TCP连接数量增多影响性能,所以和并请求就可以大大减少TCP连接的数量,同时省去了TCP握手和慢启动过程耗费的时间。

但同时这样合并的坏处就是当这个合并过后的大资源其中的任何一个小资源发生变化后,客户端就必须重新下载整个完整的大字源文件重新传输。

2.对HTTP的内容进行压缩 (有损。无损)

在HTTP的请求头当中会通过Accept-Encoding字段标记压缩的可用方法,服务器收到后会选择一个服务器支持的压缩算法对资源进行压缩,然后使用Content-Encoding告诉客户端具体使用的压缩算法。

3.使用缓存减少HTTP请求的次数

客户端会把第一次请求和响应的数据保存在本地的磁盘上面,其中的URL作为key,响应作为value

同时响应的头部信息有一个过期时间,为了防止缓存并不是最新的版本。当缓存当中的响应的时间过期之后就会让服务端重新发送请求,但是在这之前请求的Etag头部会带上第一次请求响应头部的摘要,服务器收到摘要会将本地资源的摘要和请求的摘要进行对比吗,如果不同说明客户端的缓存发生了更新需要重新发送更新后的数据,如果相同说米国缓存没有更新还是可以继续使用的返回304让客户端继续使用缓存。

2.HTTPS 

明文传输的HTTP请求会有窃听、修改和冒充的风险,使用TLS协议解决明文传输的问题。

如上图:相当于是在TCP协议和HTTP协议中间又添加了一个SSL/TLS协议来实现明文加密

所以在进行了TCP三三次握手还需要进行TLS的四次握手。简单理解TLS握手的目的就是为了通过非对称加密握手老交换算出对称加密的会话密钥来对明文进行加密保证安全。

RSA握手过程

传统的TLS握手都是基于RSA算法(简单)来实现密钥的交换,不同的密钥交换算法TLS握手的具体过程也会有一些区别。

在将TLS证书部署到服务端的时候,证书文件其实就是服务端的公钥,会在TLS握手的阶段传递给客户端,而服务器的私钥一直保留在服务端,保证私钥不能被窃取。

TLS第一次握手

客户端发送client hello消息代表进行TLS握手,同时发送客户端使用的TLS版本号、支持的密码套件以及生成的随机数,这个随机数会被服务端所保留,作为对称加密密钥的材料之一。

TLS第二次握手

服务端也会生成一个随机数然后发送Server hello的消息,以及确认支持的TLS版本信息会密码套件等等。同时发送数字证书给客户端来证明自己的身份。

上面两个随机数是后续生成会话密钥的条件,也就是使用对称加密来进行通信的会话密钥。

证书

证书包含了 公钥、持有者的信息、证书认证机构CA信息、证书有效期、签名算法。

为了证明持有者的身份防止第三方进行冒充,证书都是由CA(证书认证机构)签名下发的,保证可信度,同时签名也可以防止别人对证书内容进行篡改和伪造。

证书的验证过程中还存在一个信任链的问题,我们向CA申请的证书一般不是根证书签发的而是中间证书签发的,操作系统当中会内置许多的根证书,内置的根证书我们是可以信任的,中间证书需要进行配置从而实现证书信任。

TLS第三次握手

客户端在生成一个新的随机数,然后使用服务器的RSA公钥加密这个随机数发送给服务端。同时客户端自身也会根据这三个密钥生成对应的会话密钥。他是对称密钥用于后序HTTP请求和响应的数据加密。同时把之前所有发送的消息进行一个简单的摘要,在使用会话密钥加密之后发送过去,为了让其验证之前的握手信息是狗一致有没有被篡改过。

TLS第四次握手

也会进行和上面客户端一样的操作,最终完成整个的握手过程。

我们可以发现前面两次握手发送的还是明文,第三次握手之后发送的数据就是会话加密后的数据了。

RSA的缺点

上面的RSA密钥协商算法的最大问题是不能支持向前保密。

因为客户端传递的随机数给服务端使用的是公钥加密的,服务端接收到会使用私钥解密得到随机数,所以一旦服务端的密钥泄露了,之前所有的对话信息都会被破解。

前向保密值需要即使密钥泄露的情况下,也不能推导出将来或者之前的密钥或者信息从而获取到全部的数据。可以使用ECDHE椭圆曲线密钥交换算法来实现向前保密。

HTTPS的优化

TLS整个握手的过程最长会花掉2哥RTT的时间。

1.使用RSA密钥交换算法的TLS握手过程不禁慢而且安全性也不高(不支持向前保密性)所以尽量选择ECDHE密钥交换算法。客户端可以在第三次握手后直接发送加密的应用数据(类似于抢跑)这样接口已将2RTT时间优化到1个RTT的时间。

2.将TLS1.2升级为TLS1.3,TLS1.3大幅度优化了握手的步骤,只需要1RTT时间即可完成握手。

3.会话复用

TLS握手的目的就是为了计算出双方发送数据需要的会话密钥,所以我们将这个会话密钥保存起来那么就不需要再次进行TLS握手了。

客户端将会话密钥缓存到浏览器当中,然后再次发送消息的时候服务端根据SessionID从session当中找到对应的会话密钥来进行通信。缺点就是随着客户端的增加服务器的session存不下过多的会话密钥,以及分布式场景下session无法命中的问题。(Redis解决)

3.HTTP2

尽管对http1.1存在着许多的优化手段,但是最终的效果还是有些不尽人意,同时比如一些请求响应模型、头部信息量巨大且重复、服务器不能主动推送、并发连接消耗时间这些关键地方是无法进一步优化的,所以在这种情况下诞生了HTTP2。

HTTP/2的生升级兼容了老版本的协议(HTTP1.1)。HTTP2在URI当中没有引入新的协议名仍然使用http:和https:表示对应的协议,只需要浏览器和服务器在后面默默升级即可。用户是无感知的。

头部压缩

HTTP协议的报文是由Header+Body构成的,对于Body部分,HTTP1.1协议可以使用头字段Content-Encoding指定Body的压缩方式(gzip),节约带宽,但是Header部分却存在着些许的问题。

1.含有很多固定的字段,比如:Cookie、User Agent、Accept等,这些字段加起来也有上千字节,所以也有必要进行压缩。

2.大量请求和影响的报文里有比很多字段都是重复的,避免重复。

3.字段都是ASCLL编码,索然方便了人类观察,但是传输的效率低,有必要加成二进制编码。

HTTP/2对Header做了大部分的改造解决了上面的问题。

HTTP/2没有使用gzip来压缩头部而是开发了HPACK算法。

HPACK算法:静态字段、动态子典、Huffman编码(压缩算法)。

客户端和数据端都会建立和维护子典,使用长度较小的索引号表示重复的字符串,在使用Huffman编码压缩数据,最高可达百分之五十和百分之就是的高压缩率。

静态编码表

HTTP2为高频出现在头部字符串和字段建立了一张静态表,写入到HTTP/2框架里,不会变化.

动态表编码

静态表只包含了61种高频出现在头部的字符串,不在静态表范围内的头部字符串就需要自行构建动态表,从index62起步,同时会在编码解码的时候动态更新。

所以动态表生效的前提:必须同一个连接上,重复传输完全相同的HTTP头部,如果这个字段在这次连接上面只发送可一了,那么这个动态表生成的对应字段就没有作用了。同时动态表过大也会占用过多内存,影响服务器性能,所以会提供类似的最大配置限制一个请求能够传输的最大数量,防止动态表无限扩大。

二进制帧

HTTP2厉害的地方就在于将HTTP1的文本格式改成二进制格式的数据进行传输,极大提高了HTTP传输的效率,而且二进制数据使用位运算能高效的进行解析。

如上图:HTTP2.0把响应报文划分成了两类帧,图中的HESADERS(首部)和DATA(消息负载)是帧的类型,也就是一条HTTP响应,划分成了两类帧来进行传输,都采用二进制来进行编码。

上图就是HTTP2的二进制帧的具体结构,全部改成帧的形式进行传输。

并发传输

HTTP1.1是基于请求响应模型的,同一个连接当中,完成一个事务才能处理一下一个事务,也就是发出请求等待响应的过程当中是阻塞的,如果响应一直没有返回是无法发出下一个请求的。(串行)这就才造成了串行情况下的对头阻塞问题。

HTTP2通过 Stream的设计,多个Stream复用一条TCP的连接,达到并发的效果,从而解决HTTP1.1的串行状态下的对头阻塞问题,

HTTP2当中的Stream、Message和Frame

从上面的图片当中我们可以看到:

1个TCP连接包含了一个或者多个Stream,Stream里面包含一个或者多个Message,一个Message里面包含一个或者多个Frame,Frame是HTTP2的最小单位。

同时不同的Stream的帧是可以乱序发送的(所以相当于并发不同的Stream,这里可以简单将Stream理解成一个线程,多个Stream直接并发执行),因为每一个帧的头部都会携带着Steam ID信息,所以能够通过ID辨别出这个消息来自哪一个Stream,但是同一个Stream内部的帧必须保证是严格有序的(理解为同一个线程当中的代码必须按照顺序依次执行)。

Stream ID不能重复使用,只能顺序递增,Stream ID耗尽的时候需要发送控制帧关闭TCP连接。

Stream的默认最大上线时128个,同时可以对Stream设置不同的优先级,表示那个Stream当中的数据优先进行传递。

服务器主动推送资源

HTTP1.1不支持服务器主动推送资源,只能是客户端向服务器发送请求之后才能获取到服务器响应额资源。

HTTP2当中客户端发起的请求当中建立的Stream ID必须是奇数,服务器主动推送的Stream ID必须是偶数,服务器推送资源时必须在HTTP头部当中告诉客户端接下来在哪一个Stream种发送包体。

HTTP2.0的对头阻塞问题

HTTP2是基于TCP协议进行传输的,TCP是面向字节流的协议,TCP层必须保证收到的字节数据是完整且连续的,这样才能会将缓冲区里面的数据返回给HTTP层面的应用,如果是Stream传递的第一个字节的数据一直没有达到,那么后序带来的数据就都只能存放在内核缓冲区当中,只有当前面的数据完整的传输过来才能将完整的字节流交付给应用。如果前面有字节一直不到的话就需要整个数据进行穿新传输,这就是HTTP2的对头阻塞问题。

HTTP2.0的握手延迟 

发起HTTP请求需要先经过TCP的三次握手和TLS的四次握手,总共要经过3个RTT的往返时间才能够发出请求,同时TCP具有拥塞控制的特性,所以TCP连接刚开始建立的时候会有一个慢启动的过程,会对TCP的传输速率造成一定的影响。

网络移动需要重新连接

TCP是由四元组(源IP地址、目标IP地址、源端口和目标端口)确定的,所以当我们切换网络(比图数据流量切换陈wifi)的时候IP地址就会发生变化,就导致TCP连接断开需要重新握手建立连接。以及当我们在告诉移动的高速公路上的时候与,随着信号基站的移动我们的数据的IP地址也会发生变化,就会导致连接的重现建立。

所以上面这些其实都是TCP这个协议固有的一些问题,无论在进行怎样的优化都不能区客服这些问题,所以就诞生了下面的HTTP3,底层待用UDP协议来实现通信。

HTTP/3

最新推出的请求目前还没有正式推出使用。

QUIC协议

因为我们知道UDP是一个简单的不可靠的传输协议,并且UDP包之间的传输是无序的,也不需要握手建立连接,所以天然比TCP要快上很多。

因为HTTP2使用TCP一定会有一些问题无法客克服,所以HTTP3使用UDP协议进行传输,同时实现了QUIC协议来保证UDP可以有类似于TCP的连接管理、拥塞控制、流量控制等特性,让UDP变得可靠从而不用但因数据丢失等问题。

QUIC的优点有很对,比如没有对头阻塞问题,更快的建立连接,连接可以支持迁徙等等。

无队头阻塞问题

QUIC协议有类似于HTTP2 Stream于多路复用的概念,也可以在同一条连接上面传输多个Stream。(每一个Stream就可以简单理解为是一个HTTP请求)

QUIC对每一个数据包都有一个序号作为唯一的标识,当某个流种的一个数据包丢失了,即使这个流当中的其他数据包达到了也不会被接收读取,直到QUIC重传丢失的报文数据才能整个交给应用层。

在HTTP2当中只要这个TCP连接当中的一个流出现了问题,所有的流都活跟着受影响遭到阻塞,因为这是TCP层面的重传机制导致的,但是HTTP3只有对应的丢失文件的流需要等到数据的重传即可,Stream之间可以理解为相互隔离,相互不受影响。

更快的建立连接

http2的TCP和TLS是分开的,需要先TCP的三次握手在进行TLS的三次握手,浪费时间。HTTP3只需要进行1个RTT时间的QUIC的三次握手即可,握手的目的只需要确认双方的连接ID即可,同时连接的迁移问题也是通过这个ID解决。

QUIC协议内部包含了TLS1.3,这需要经过1RTT三次握手完成加密,甚至在第二次连接的时候,应用数据包可以和QUIC握手信息一起发送,达到0RTT的效果。

连接迁移

在前面我们提到,基于 TCP 传输协议的 HTTP 协议,由于是通过四元组(源 IP、源端口、目的 IP、目的端口)确定一条 TCP 连接。

那么当移动设备的网络从 4G 切换到 WiFi 时,意味着 IP 地址变化了,那么就必须要断开连接,然后重新建立连接,而建立连接的过程包含 TCP 三次握手和 TLS 四次握手的时延,以及 TCP 慢启动的减速过程,给用户的感觉就是网络突然卡顿了一下,因此连接的迁移成本是很高的。

而 QUIC 协议没有用四元组的方式来“绑定”连接,而是通过连接 ID 来标记通信的两个端点,客户端和服务器可以各自选择一组 ID 来标记自己,因此即使移动设备的网络变化后,导致 IP 地址变化了,只要仍保有上下文信息(比如连接 ID、TLS 密钥等),就可以“无缝”地复用原连接,消除重连的成本,没有丝毫卡顿感,达到了连接迁移的功能。

  • 32
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值