likes
comments
collection
share

初识 HTTP 2.0 (一)

作者站长头像
站长
· 阅读数 14

初识 HTTP 2.0 (一)

相较于 1.1 版本, 2.0 版本,做了哪些改变呢?今天我们就来一探究竟。老规矩,先看理论,再来实践。

理论

我们要知道,http 的 2.0 版本,首次发布是在 2015 年的 5 月份,距离其 1.1 版本(1997 年 7 月)过了 18 年之久。那官方是如何定义 http 2.0 的呢?打开 RFC Editor,在第二章 Http/2 Protocol Overview 中,对重要特性作了总结性的说明。

初识 HTTP 2.0 (一)

从内容中,我们可以得知,2.0 版本的主要特性包括:

  • 传输的最小单元从 http 1.1 版本的文本格式,变成了,不同的,完成不同的事情
  • 多路复用,通过流式传输,减少多个 http 请求之间的阻塞
  • 流量控制和优先级控制
  • 数据压缩
  • 服务端推送

那这些新特性具体长的什么样呢?接下来,我们就通过 Chrome 浏览器的开发者工具和 wireshark 抓包工具,一起来揭开它神秘的面纱。

实践

首先,我们准备一个支持 http 2.0 协议的服务,因为 http 2.0 是建立在 TLS 协议基础之上的,所以,我们还要准备一个证书,这里项目的版本及证书如下:

  • jdk: 17
  • spring boot: 3.1.0
  • tls: 通过 keytool 生成的自签名证书

  1. 对于 spring boot 项目来说,启用对 http 2.0 协议的支持还是很简单的,只需要打开配置即可: 初识 HTTP 2.0 (一)

  2. 接下来,我们准备一个简单的 html 页面,里面包含几个 css 文件,js 文件和图片。当我们使用浏览器访问页面的时候,浏览器首先会向服务端请求 index.html 页面,然后解析到页面依赖于其它文件,就会再次向服务器发起请求,下载 css 文件,js 文件,图片等信息。 初识 HTTP 2.0 (一)

  3. 项目准备好以后,我们将打好的 jar 包拷贝到虚拟机上,然后启动服务,从日志中我们可以看到,服务已经可以支持 http 2.0 版本了 初识 HTTP 2.0 (一)

  4. 我们修改 yml 文件,将端口号改为 9999,并关掉对 http2 的支持,重新打包,并启动。这样我们就可以方便的去对比,浏览器和服务端面对不同版本的协议时,都是如何处理的。 初识 HTTP 2.0 (一) 初识 HTTP 2.0 (一)

  5. 执行 tcpdump 命令,分别监听 8888 端口和 9999 端口,并将监听到的内容写入文件。 初识 HTTP 2.0 (一)

  6. 打开 Chrome 浏览器,打开开发者工具的 Network 面板,分别访问 8888 端口和 9999 端口的 index.html 页面。 初识 HTTP 2.0 (一) 初识 HTTP 2.0 (一)

从执行结果里,我们可以观察到:

  1. 在协议一栏,已经可以明显看出当前浏览器和服务器通讯时,采用的 http 协议版本。
  2. 对于 8888 端口的请求,浏览器和服务器只在第一次请求 html 页面时,建立了一次连接。而当浏览器访问 9999 端口时,除了访问 html 页面建立了一次连接以外,还在请求下载 9113.png 图片时,又和服务器建立了一次连接。 初识 HTTP 2.0 (一) 这里其实是 Chrome 浏览器的一个优化机制:当浏览器和一个域名建立连接时,会自动和服务器建立多个连接,这样,每个连接执行多个 http 请求,从而达到并发的能力,以此来优化页面的打开速度。而浏览器之所以要做这样的事情,就是因为 http 协议在 1.1 版本中,存在一个队头阻塞问题(Head-of-line (HoL) blocking)。 就是说,当第一个 http 请求发送后,后续其它的 http 请求都要等前一个请求结束,才能发送下一个请求。我们假设一个页面包含100张图片,如果第一个下载图片的请求阻塞住了,那后续99个下载图片的请求都要排队,可想而知,我要多久以后才能看到这个页面?因此,浏览器会自动建立多个连接,同时下载多个图片。但是建立过多的连接对服务端也会造成压力,所以一般来说,浏览器会和同一个域名建立至多6个连接,以达到保证速度和节省资源的平衡。

接下来,我们再来看看 wireshark 的抓包结果。首先是对 9999 端口抓包的结果,过滤 http 协议:

初识 HTTP 2.0 (一) 初识 HTTP 2.0 (一) 初识 HTTP 2.0 (一)

查看 37 号数据包和 128 号数据包,可以看到两次 http 请求分别在不同的 tcp 连接上发送的,这也和我们在浏览器的开发者工具看到的结果是一致的,接着我们以 2476 端口为例,我们可以看到,后一个请求都是要等到前一个请求结束以后,才会发送出去。点开任一请求或者响应记录,可以看到传输的格式为文本格式。

初识 HTTP 2.0 (一)

初识 HTTP 2.0 (一)

查看 8888 端口的抓包结果,同样,先过滤 http2 协议:

初识 HTTP 2.0 (一)

  1. 查看每一个数据包后,可以看到,在浏览器基于 http 2.0 协议进行通讯时,只和服务端建立了一次连接

  2. 浏览器向服务端请求第一个 html 页面时,发送了一个带有 HEADERS【1】标记的数据包,而服务端在向浏览器返回数据时,发送了两个带有 DATA【1】标记的数据包,从而完成了一次 http 请求。这个,就是 http 2.0 的最小传输单元,关于帧的具体内容,在下篇文章中,我们可以具体分析,这里先有一个印象。 初识 HTTP 2.0 (一)

  3. 当请求页面信息结束以后,我们可以看到第 38, 39, 41 号数据包,分别去请求了 css 样式文件和图片,但是他们并没有等待其它请求结束再发送请求,而是并发的将请求发送到服务端。而后面服务端在返回数据时,也没有按照顺序一次性的将所有数据返回,而是分成了不同的帧,乱序的返回。这就是上面说的多路复用的特性。

  4. 我们可以看到,同样是请求 index.html 页面,http 2.0 版本的 header 长度只有 564,而在 http 1.1 版本,长度达到了 813,这也就是数据压缩的特性

总结

经过上面的操作,我们对 http 2.0 协议有了一个初步认识,在后续的文章中,我们会对其重要特性,再做更多的学习和介绍。

(感谢阅读,如有不正确之处,欢迎指教)