20.SPDY_QUIC_HTTP2_HTTP3

Wireshark解密HTTPS

◼ 设置环境变量SSLKEYLOGFILE(浏览器会将key信息导出到这个文件)

先在电脑上创建ssl.log文件

点击计算机>属性>高级系统设置>环境变量>用户变量>新建

在这里插入图片描述

◼ 设置完成后,最好重启一下操作系统

◼ 在Wireshark中选择这个文件

编辑 → 首选项 → Protocols → TLS

在这里插入图片描述

先点击以太网>输入tcp port 443>enter

在浏览器访问baidu.com

只有搞了这些东西,我们才可以解析出来用了什么协议

在这里插入图片描述

HTTP2是基于二进制帧的概念

◼ 如果环境变量不管用,可以直接设置浏览器的启动参数(下图是使用了Rolan进行启动)

在这里插入图片描述

配置服务器HTTP—生成证书

使用什么协议,是由后端工程师决定的

在这里插入图片描述

浏览器自带CA机构的公钥,可以自动验证证书

TCP三次握手,TSL十次连接,浏览器那边自动就做了,不用我们来

做为客户端,我们只要去访问URL就可以了,在前端把协议一改,用HTTPS去访问

做为服务器,我们要把证书放上去,顺便告诉客户端去哪里找这个证书

到时候,做为公司,我们去买商用的证书就可以了,比如阿里云

◼ 环境:Tomcat9.0.34、JDK1.8.0_251

◼ 首先,使用JDK自带的keytool生成证书(一个生成免费证书的网站: https://freessl.org/)

在这里插入图片描述

由于JDK的bin目录,我们已经配送到了环境变量里面去了,意味着,我们可以在cmd界面直接敲

keytool -genkeypair -alias mj -keyalg RSA -keystore F:/mj.jks

在这里插入图片描述

代码解释

在这里插入图片描述

jks,java keystore

在这里插入图片描述

配置服务器HTTPS—配置Tomcat

◼ 将证书*.jks文件放到TOMCAT_HOME/conf目录下

在这里插入图片描述

配置服务器HTTPS—配置Tomcat

打开TOMCAT_HOME/conf/server.xml

把8080端口的Connector给注释掉

把HTTPS的模板给复制上来

在这里插入图片描述

◼ 修改TOMCAT_HOME/conf/server.xml中的Connector

在这里插入图片描述

就改一个地方(certificateKeystoreFile),添一个地方(certificateKeystorePassword)

在这里插入图片描述

服务器添加证书成功

因为浏览器不认识我们的自签证书,所以显示不安全

但是我们真的是用TLS加密通道的,可以通过Wireshark抓包来查看

在这里插入图片描述

在这里插入图片描述

开发人员做的是请求这个地址,至于HTTP请求库自带的功能怎么搞,跟我们没有关系

利用HTTP请求库去请求右边HTTPS服务器,至于验证证书跟我们没有关系

左边要有验证证书的能力,右边放一个证书,给左边下载

注释:实验做完,记得改过来,不要去污染我们的环境

HTTP协议的不足(HTTP/1.1)

看底层,只要你用的是HTTP/1.1,你就存在下面的问题

◼ 同一时间,一个连接只能对应一个请求

连接可以复用,但是你要排队,前面的结束了,你后面的才可以过去

为了能够实现请求并发,可以同时建立多个连接

针对同一个域名,大多数浏览器允许同时最多6个并发连接

◼ 只允许客户端主动发起请求

首先我们的第一个请求是获取网站的html,但浏览器在解析的过程当中,发现要去加载CSS、图片、JS

所以我们在加载一个网站的时候要发起很多次请求,因为HTTP/1.1的特性,服务器做不到一次请求给我们发很多东西,只能是请求和应答的模式,所以我们要发起很多次请求

一个请求只能对应一个响应

◼ 同一个会话的多次请求中,头信息会被重复传输

在这里插入图片描述

在这个会话过程中,为了证明自己的身份,每一次请求都要发送cookie过去

通常会给每个传输增加500~800字节的开销

如果使用 Cookie,增加的开销有时会达到上千字节

每一次请求都要重复发上千字节

SPDY

◼ SPDY(speedy的缩写),是基于TCP的应用层协议,它强制要求使用SSL/TLS

2009年11月,Google宣布将SPDY作为提高网络速度的内部项目

作为改进HTTP/1.1的项目,因为它觉得HTTP/1.1太慢了,每次都要重复传一些东西,消耗流量;服务器无法发送数据过来;同一时间,一个连接只能对应一个请求,很麻烦,假设一个网站要100次请求,那要搞到什么时候

HTTP是一个全球标准,它要有标准组织认可才可以改,所以Google先自己用,等自己用了没问题,在推广

◼ SPDY与HTTP的关系

SPDY并不用于取代HTTP,它只是修改了HTTP请求与响应的传输方式

HTTP报文先传给SPDY,SPDY进一步压缩进行一系列处理等等,然后交给TLS

之前HTTP报文段就是文本,字符串

SPDY对HTTP报文进行加工,处理,让它传输的更快,最终在加密交给TCP

只需增加一个SPDY层,现有的所有服务端应用均不用做任何修改

以前我们编写的代码通通不用动,包括前端和后端,因为我们编写的代码是面向HTTP开发的

SPDY属于服务器的配置,代码不用动

SPDY是HTTP/2的前身

✓ 2015年9月,Google宣布移除对SPDY的支持,拥抱HTTP/2

推动变成国际标准,但是之前大家用的是HTTP,为了方便推动就改成了HTTP/2

在这里插入图片描述

HTTP/2

右键点击Status,选择Protocol,就可以查看请求用了什么协议

在这里插入图片描述

◼ HTTP/2,于2015年5月以RFC 7540正式发表

根据W3Techs的数据,截至2019年6月,全球有36.5%的网站支持了HTTP/2

◼ HTTP/1.1和HTTP/2速度对比

http://www.http2demo.io/

https://http2.akamai.com/demo

快了四倍

在这里插入图片描述

HTTP/1.1,一条横线就是一个连接,每一个连接是可以复用的,六个连接包揽了100多个请求

在这里插入图片描述

HTTP/2用一个连接,搞定了所有的请求

◼ HTTP/2在底层传输做了很多的改进和优化,但在语意上完全与HTTP/1.1兼容

速度特别快

比如请求方法(如GET、POST)、Status Code、各种Headers等都没有改变

API层面没有变,对我们开发者没有任何影响

因此,要想升级到HTTP/2

✓ 开发者不需要修改任何代码(JAVA、安卓、IOS等代码)

✓ 只需要升级服务器配置、升级浏览器

就像配置HTTPS一样

浏览器要升级一下,才会有SPDY的功能

操作系统内核里面包含了处理传输层以下的东西的API,为了应用TCP的新特性,我们要去升级一下操作系统内核,内核里面要去改代码,这是很麻烦的,但是SPDY就不一样了

应用层可以由开发者决定,比如加上一层SPDY,我们只要升级一下应用层的软件就可以了

HTTP/2的RFC文档里面不强求使用TSL/SSL,但是现在只要使用HTTP/2的公司基本上都有用TSL/SSL

HTTP/2的速度非常快,采用TSL/SSL浪费的时间基本上可以忽略不记,完全可以上安全层

HTTP/2的特性—二进制格式

在这里插入图片描述

◼ HTTP/2采用二进制格式传输数据,而非HTTP/1.1的文本格式(字符串)

打散,把HTTP报文编码成二进制格式,不是我们一眼可以看懂的

把信息转化成二进制帧

◼ 二进制格式在协议的解析和优化扩展上带来更多的优势和可能

先把报文打散,在传输

HTTP/2—一些基本概念

◼ 数据流:已建立的连接内的双向字节流,可以承载一条或多条消息

在这里插入图片描述

在一次请求当中,就好比一个数据流,双向的,类似一个管道

所有通信都在一个TCP连接上完成,此连接可以承载任意数量的双向数据流

同一个时间,一个TCP连接,可以处理N个请求

◼ 消息:与逻辑HTTP请求或响应消息对应,由一系列帧组成

我们发的和接收的内容

◼ 帧:HTTP/2通信的最小单位,每个帧都包含帧头(会标识出当前帧所属的数据流)

在这里插入图片描述

来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装

在这里插入图片描述

在这里插入图片描述

客户端给服务器的是5号流,给客户端的是1,3号流,交错发送,所以非常快

数据流一排排的过去,他是逻辑上的概念,真实情况数据流的帧是交错发送的,并发的,随便发,在拼接的时候,才需要管顺序

在这里插入图片描述

HTTP/2—一些基本概念

在这里插入图片描述

在逻辑上有N号流,每一条流都是双向的,在上面有非常多的帧

HTTP/2的特性—多路复用(Multiplexing)

◼ 客户端和服务器可以将 HTTP消息分解为互不依赖的帧,然后交错发送,最后再在另一端把它们重新组装起来

◼ 并行交错地发送多个请求,请求之间互不影响

◼ 并行交错地发送多个响应,响应之间互不干扰

◼ 使用一个连接并行发送多个请求和响应

◼ 不必再为绕过HTTP/1.1限制而做很多工作

因为HTTP/1.1的限制,开发人员想尽各种办法,去提高我们的网速

尽量减少请求数量

比如image sprites、合并CSS\JS、内嵌CSS\JS\Base64图片、域名分片等

image sprites:精灵图片,雪碧图

合并CSS\JS:把很多个文件合并成一个文件,比如你搞四个CSS文件,就要搞四个请求,我们可以把四个文件合并成一个文件,那只需要一个请求

内嵌CSS\JS:

在这里插入图片描述

把CSS\JS代码内嵌进HTML里面去,响应给浏览器,就不用下次在请求

内嵌Base64图片:

先去访问工具网站,https://c.runoob.com/front-end/59/

上传图片,即可得到图片的BASE64编码,

在这里插入图片描述

在HTML代码中,引入BASE64编码,即可

在这里插入图片描述

不过,因为我的像素过大,所以我最终的结果,图片是损坏的

在这里插入图片描述

BASE64图片的原则是,把图片的像素信息进行编码,转成字符串进行描述

这样做,就可以减少图片的请求,因为图片数据已经包含在HTML里面了

只适合小图片,图片越大,像素越多,字符串就越长,就会导致HTML超长,不太好维护

浏览器根本就没有发请求,直接去解析字符串,图片数据已经在BASE64图片里面了,这个是给我们看的

在这里插入图片描述

在这里插入图片描述

你的N多个请求都在一个连接上发,而且这个连接上可以有很多流,交错发送

底层用的是TCP,TCP是有序的,最终拿数据是按照顺序来的

image sprites

◼ image sprites(也叫做CSS Sprites),将多张小图合并成一张大图

最后通过CSS结合小图的位置、尺寸进行精准定位

开发者只要知道,我想要的图片相对这张大图来说,你左边距离多少,上边距离多少,图片宽度多少,高度多少,这样我就可以实现精准定位,然后把它抠出来,显示出来

代码不经常敲就会忘

在这里插入图片描述

精灵图这个技术实在是恶心,需要多方配合,美工需要把这张图片合在一起,开发者需要知道每张图片的具体位置,所以会有一个列表信息,把图片的位置给列出来,还有一个参照表

在这里插入图片描述

但是我们现在有HTTP2就不用这么搞了,我们永远只有一个连接,所有的数据都在里面传输,而且这些数据还是打散的,速度非常快

精灵图片的排布顺序是乱的,它是根据算法生成,是为了尽量让空间小一点,只要加一张图片,整张精灵图片都会变,排布顺序全部打乱

域名分片:

一个域名最多只能有六个连接,搞一些子域名,把图片放到那个域名的图片里面去,直接访问那个域名

穿插一些iframe,在这个iframe里面放一些请求,这样就可以去请求其它的页面

HTTP/2的特性—多路复用(Multiplexing)

在这里插入图片描述

以前,同时请求3个文件,就要3个连接,一个连接,同时只能处理一个请求

现在,一个连接可以处理N个请求,数据可以打散,交错传送,非常棒

在这里插入图片描述

我只打开一个连接,持续打开,你后面还有请求,继续用这个连接,可以同时并发传送数据,棒极了!

HTTP/2的特性—优先级

◼ HTTP/2 标准允许每个数据流都有一个关联的权重和依赖关系

可以向每个数据流分配一个介于1至256之间的整数

每个数据流与其他数据流之间可以存在显式依赖关系

A可能依赖于B,B可能依赖于C

◼ 客户端可以构建和传递“优先级树”,表明它倾向于如何接收响应

设定一个优先级,告诉服务器,我先接收那个,后收那个

◼ 服务器可以使用此信息通过控制CPU、内存和其他资源的分配设定数据流处理的优先级

在资源数据可用之后,确保将高优先级响应以最优方式传输至客户端

HTTP/2的特性—优先级

在这里插入图片描述

权重越大,代表优先级越高。

隐式根流:看不见的数据流

◼ 应尽可能先给父数据流分配资源

◼ 同级数据流(共享相同父项)应按其权重比例分配资源

① A、B依赖于隐式“根数据流”,A获得的资源比例是12/16,B获得的资源比例是4/16

谁获得的资源比例高,谁就优先发,所以A先发

② D依赖于根数据流,C依赖于D,D应先于C获得完整资源分配

③ D应先于C获得完整资源分配,C应先于A和B获得完整资源分配,B获得的资源是A所获资源的1/3

④ D应先于E和C获得完整资源分配,E和C应先于A和B获得相同的资源分配,B获得的资源是A所获资源的1/3

HTTP/2的特性—头部压缩

在这里插入图片描述

会跟踪你以前发过的请求,第二次请求会根据压缩算法,只会发之前没有发过的,发重要的东西

浏览器会存储之前的请求,进行比对,把之前发过的请求头给删掉

无状态,请求和请求之间是独立的,它不会去管你上次有没有带Cookie,请求的是什么。它就是去对比,把你重复的部分给删掉,它才不管你发的是什么内容

只是保留了你上次发的请求而已 ,相当于是一个记录的行为

HTTP2作为底层,记录了HTTP发过的请求

◼ HTTP/2使用HPACK压缩请求头和响应头

可以极大减少头部开销,进而提高性能

◼ 早期版本的HTTP/2和SPDY使用 zlib压缩

可以将所传输头数据的大小减小85%~88%

但在2012年夏天,被攻击导致会话劫持

后被更安全的HPACK取代

HTTP/2的特性—头部压缩

在这里插入图片描述

静态表,本来索引里面就会有的东西,常用的、可能会用到的,建立一张表出来,把动态表放到后面去

动态表,随着不断的发请求,就会有一些新的请求头

在客户端和服务器各保留一份,双方都会保存请求过的东西

索引表里面有的,只发索引号,服务器会根据索引号找到对应的头信息

HTTP/2的特性—服务器推送(Server Push)

◼ 服务器可以对一个客户端请求发送多个响应

前提还是要客户端发送请求

只要是HTTP,肯定是请求—应答模式,先有请求才有应答

除了对最初请求的响应外,服务器还可以向客户端推送额外资源,而无需客户端额外明确地请求

在这里插入图片描述

例如我们请求京东的HTML,发现里面还需要CSS、IMG、JS,那服务器就会把这些资源推过来,相当于节省了请求

在这里插入图片描述

流是双向的,有过去就有回来

你只有一个请求,但是我却给你多个响应

HTTP/2的问题—队头阻塞(head of line blocking)

在这里插入图片描述

由于TCP的按序特性,当TCP接收的时候少了一个包时,后面东西就不会收了,这个时候只能重发

这个问题是由TCP决定的,而不是HTTP的问题

QUIC协议,传输的数据互不影响,当接收的时候少收了一个包时,可以把后面的优先提出来,丢的那个包后面补发就可以了,因为它底层使用的是UDP协议

在这里插入图片描述

HTTP/2的问题—握手延迟

在这里插入图片描述

QUIC直接跟你说我要给你发送数据,随后就开始仍数据给你,不用跟你握手,0秒建立连接

◼ RTT(Round Trip Time):往返时延,可以简单理解为通信一来一回的时间

HTTP/2的问题—握手延迟

在这里插入图片描述

在这里插入图片描述

QUIC跟你讲我要跟你建立连接,然后直接就给你仍数据,不用跟你握手

HTTP/3

◼ Google觉得HTTP/2仍然不够快,于是就有了HTTP/3

存在握手延迟、队头阻塞的问题

HTTP/3由Google开发,弃用TCP协议,改为使用基于UDP协议的QUIC协议实现

QUIC(Quick UDP Internet Connections),译为:快速UDP网络连接,由Google开发,在2013年实现

于2018年从HTTP-over-QUIC改为HTTP/3

在这里插入图片描述

传输层使用UDP协议,应用层加了一个QUIC协议,TLS升级为1.3版本,压缩算法改成了QPack,但仍然保留了流的概念

可以理解为在HTTP2的基础上加了层QUIC

HTTP/3—疑问

◼ HTTP/3基于UDP,如何保证可靠传输?

由QUIC来保证

在这里插入图片描述

之前是TCP层跟TCP层对接,你那边拿到了多少包,有没有漏收,漏收了我发给你,来保证可靠传输,丢包和请求失败都是TCP层报给HTTP层

在这里插入图片描述

丢了就丢了,对方的UDP层能收多少是多少,导致 HTTP层拿到的是不完整的,比如我们要图片,可能图片只拿到了一半,甚至连一半都没有

在这里插入图片描述

QUIC层会告诉对方自己发了多少个,漏了会补发,它们之间存在沟通的渠道,少了的那一方,会让对方QUIC层补发,所以我用了UDP层我也无所谓,因为QUIC层可以保证可靠传输

TCP之所以可以保证可靠传输,是因为它复杂的头部信息,TCP里面有代码可以保证可靠传输,那QUIC层也是一样的,也是有代码来保证可靠传输

就相当于是把TCP层用来保证可靠传输的那部分给取了出来,重新命了个名

◼ 为何Google不开发一个新的不同于TCP、UDP的传输层协议?

Google有能力去开发一个新的传输协议,例如GDP,兼具TCP和UDP的功能(可靠传输),解决HTTP/2存在的问题(队头阻塞)

这样子,就不会有多出来的一层,还要去写QUIC

在这里插入图片描述

目前采用的是,队头阻塞用UDP解决,可靠传输,我自己写一个

目前世界上的网络设备基本只认TCP、UDP

路由器、电脑、手机这些设备,固化在里面的,只认这两个

那就代表我们要研发新的设备,现在互联网上的设备都不能用了,谁出钱,我凭什么换

如果要修改传输层,意味着操作系统的内核也要修改

SocketAPI发送请求的,它是系统内核里面的东西,传输层一改,它也要跟着改

修改传输层,这是一个不现实的东西

另外,由IETF标准化的许多TCP新特性都因缺乏广泛支持而没有得到广泛的部署或使用

因此,要想开发并应用一个新的传输层协议,是极其困难的一件事情

这是一个兼容问题

HTTP/3不是最终标准,它还在改进当中

HTTP/3的特性—连接迁移

◼ TCP基于4要素(源IP、源端口、目标IP、目标端口)

也可以叫四元组

在这里插入图片描述

只有知道这四要素才可以建立连接,端口往端口发

切换网络时至少会有一个要素发生变化,导致连接发生变化

在这里插入图片描述

双方IP确定,端口确定,即可建立连接

手机自带蜂窝网络(移动网络),切换到WIFI,IP可能会变,以前的网络就不能用了

TCP的头部有源IP,目标IP,这个是改变不了的,以前的网络会超时断开,因为它找不到源IP了,这个时候只能等待一段时间,在重新建立连接

这就是当我们手机切换网络时,会卡顿的原因,甚至玩游戏会掉线

当连接发生变化时,如果还使用原来的TCP连接,则会导致连接失败,就得等原来的连接超时后重新建立连接

所以我们有时候发现切换到一个新网络时,即使新网络状况良好,但内容还是需要加载很久

如果实现得好,当检测到网络变化时立刻建立新的TCP连接,即使这样,建立新的连接还是需要几百毫秒的时间

◼ QUIC的连接不受4要素的影响,当4要素发生变化时,原连接依然维持

IP、端口可能会变

QUIC连接不以4要素作为标识,而是使用一组Connection ID(连接ID)来标识一个连接

我们发过去的包里面有Connection ID,但还是需要4要素,因为底层需要,UDP、IP,它们需要IP来找到对方,需要端口找到对应的应用,建立连接

尽管底层的四要素发生了变化,只要你Connection ID不变,我就可以尽全力保证你连接不断开

我指的是QUIC

即使IP或者端口发生变化,只要Connection ID没有变化,那么连接依然可以维持

比如

✓ 当设备连接到Wi-Fi时,将进行中的下载从蜂窝网络连接转移到更快速的Wi-Fi连接

✓ 当Wi-Fi连接不再可用时,将连接转移到蜂窝网络连接

HTTP/3的特性—向前纠错(暂时了解)

还没有成为标准,仍然有改进的空间

TCP丢包,它会超时重传

向前纠错,每个包都有冗余数据,多多少少包含有其它数据包的数据,这样子可以借助其它数据包的冗余数据,组装回丢掉的包

只适合丢掉少量的数据包,比如四个丢一个,要是丢两个就不行了

HTTP/3的问题—操作系统内核、CPU负载

◼ 据Google和Facebook称,与基于TLS的HTTP/2相比,它们大规模部署的QUIC需要近2倍的CPU使用量

Linux内核的UDP部分没有得到像TCP那样的优化,因为传统上没有使用UDP进行如此高速的信息传输

因为我们以前使用的请求大部分是用TCP,例如HTTP请求、邮件都是基于TCP的

TCP和TLS有硬件加速,而这对于UDP很罕见,对于QUIC则基本不存在

还是有很长的路要走

◼ 随着时间的推移,相信这个问题会逐步得到改善

猜你喜欢

转载自blog.csdn.net/m0_53008479/article/details/121256791