0%

【http】http2入门

[TOC]

概述

HTTP2的核心概念有哪些

  • 二进制分帧层,在 http 与 tcp 层中间的一层,将传输的数据编码为二进制的帧格式
  • 请求与响应复用,http2采用tcp永久连接,在这个连接上抽象出数据帧(被编码的传输数据),消息(一条完整的需要发送的消息),数据流(双向字节流,用于承载消息(实际上是消息被编码的帧))
  • 服务器推送,一问多答(一次请求多次相应)
  • 头部压缩,相同的头在同一连接上,在再次请求时,不用显式地传递(客户端和服务端维护一个头索引表)

如何查看当前使用的是http哪个协议

核心概念

二进制分帧

HTTP/2 所有性能增强的核心在于新的二进制分帧层,它定义了如何封装 HTTP 消息并在客户端与服务器之间传输。

这里所谓的“层”,指的是位于套接字接口与应用可见的高级 HTTP API 之间一个经过优化的新编码机制:HTTP 的语义(包括各种动词、方法、标头)都不受影响,不同的是传输期间对它们的编码方式变了。HTTP/1.x 协议以换行符作为纯文本的分隔符,而 HTTP/2 将所有传输的信息分割为更小的消息和帧,并采用二进制格式对它们编码。

数据流,消息和帧

  • 连接: tcp 连接
  • 数据流(stream):已建立的连接内的双向字节流,可以承载一条或多条消息。
  • 消息(message):与逻辑请求或响应消息对应的完整的一系列帧。
  • 帧(frame):HTTP/2 通信的最小单位,每个帧都包含帧头,至少也会标识出当前帧所属的数据流。

这些概念的关系总结如下:

  • 所有通信都在一个 TCP 连接上完成,此连接可以承载任意数量的双向数据流。
  • 每个数据流都有一个唯一的标识符和可选的优先级信息,用于承载双向消息。
  • 每条消息都是一条逻辑 HTTP 消息(例如请求或响应),包含一个或多个帧。(程序一次可以发送一次消息,且不用等待返回,就继续发送新的消息,而这个消息会在同一个数据流中传递
  • 帧是最小的通信单位,承载着特定类型的数据,例如 HTTP 标头、消息负载等等。 来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装。

请求与响应复用

我们知道,在HTTP 1.x中,我们是可以并行请求的。但是,浏览器对于同一个域名的并行请求是有上限的(FireFox, Chrome上限6个 )。所以很多网站的静态资源站可能会有多个。虽然http1.x里有keep-alive可以避免TCP三次握手,但是keep-alive又是串行的。所以要么并行多握手,要么串行不握手,都不是最好的结果,我们希望的是并行也不握手。

幸运的是HTTP/2解决了这个问题。当客户端与服务端建立连接后,就会在双方建立一个双向流通道。这个流通道,可以同时包含多个消息(http请求),不同消息各自的数据帧在流里可以乱序并行的发送,不会互相影响与堵塞,从而实现了一个TCP链接,并发执行N个http请求。通过提高并发,减少TCP连接开销,HTTP/2的速度得到了很大提升,尤其是在网络延迟比较高的情况下。这个是如何实现的呢,它的实现是因为 http2 有了二进制分帧层。

将 HTTP 消息分解为独立的帧,交错发送,然后在另一端重新组装是 HTTP 2 最重要的一项增强。事实上,这个机制会在整个网络技术栈中引发一系列连锁反应,从而带来巨大的性能提升,让我们可以:

  • 并行交错地发送多个请求,请求之间互不影响。
  • 并行交错地发送多个响应,响应之间互不干扰。
  • 使用一个连接并行发送多个请求和响应。
  • 不必再为绕过 HTTP/1.x 限制而做很多工作(请参阅针对 HTTP/1.x 进行优化,例如级联文件、image sprites 和域名分片。
  • 消除不必要的延迟和提高现有网络容量的利用率,从而减少页面加载时间。

数据优先级

HTTP/2 标准允许每个数据流都有一个关联的权重和依赖关系,来保证高优先级的流优先被 client 和 server 的操作系统和处理程序处理。

每个来源一个连接

有了新的分帧机制后,HTTP/2 不再依赖多个 TCP 连接去并行复用数据流;每个数据流都拆分成很多帧,而这些帧可以交错,还可以分别设定优先级。 因此,所有 HTTP/2 连接都是永久的,而且仅需要每个来源一个连接,随之带来诸多性能优势。

大多数 HTTP 传输都是短暂且急促的,而 TCP 则针对长时间的批量数据传输进行了优化。 通过重用相同的连接,HTTP/2 既可以更有效地利用每个 TCP 连接,也可以显著降低整体协议开销。不仅如此,使用更少的连接还可以减少占用的内存和处理空间,也可以缩短完整连接路径(即,客户端、可信中介和源服务器之间的路径) 这降低了整体运行成本并提高了网络利用率和容量。 因此,迁移到 HTTP/2 不仅可以减少网络延迟,还有助于提高通量和降低运行成本。

流控制

流控制是一种阻止发送方向接收方发送大量数据的机制,以免超出后者的需求或处理能力。

服务器推送

HTTP/2 新增的另一个强大的新功能是,服务器可以对一个客户端请求发送多个响应。 换句话说,除了对最初请求的响应外,服务器还可以向客户端推送额外资源,而无需客户端明确地请求。

标头压缩

每个 HTTP 传输都承载一组标头,这些标头说明了传输的资源及其属性。 在 HTTP/1.x 中,此元数据始终以纯文本形式,通常会给每个传输增加 500–800 字节的开销。如果使用 HTTP Cookie,增加的开销有时会达到上千字节。为了减少此开销和提升性能,HTTP/2 使用 HPACK 压缩格式压缩请求和响应标头元数据,这种格式采用两种简单但是强大的技术:

  1. 这种格式支持通过静态霍夫曼代码对传输的标头字段进行编码,从而减小了各个传输的大小。
  2. 这种格式要求客户端和服务器同时维护和更新一个包含之前见过的标头字段的索引列表(换句话说,它可以建立一个共享的压缩上下文),此列表随后会用作参考,对之前传输的值进行有效编码。

利用霍夫曼编码,可以在传输时对各个值进行压缩,而利用之前传输值的索引列表,我们可以通过传输索引值的方式对重复值进行编码,索引值可用于有效查询和重构完整的标头键值对。

作为一种进一步优化方式,HPACK 压缩上下文包含一个静态表和一个动态表:静态表在规范中定义,并提供了一个包含所有连接都可能使用的常用 HTTP 标头字段(例如,有效标头名称)的列表;动态表最初为空,将根据在特定连接内交换的值进行更新。

golang 实现 server push

server push 简单说就是 client 请求一次,但是 server 返回几次。个人感觉这个东西还是比较鸡肋的,这是因为现在的文件资源很多都是放在cdn的,这样 server push 的意义就不是很大了。

server push 不仅可以用作拉取静态资源,我们的 cgi 请求即 ajax 请求同样可以使用 server push 来发送数据。

参考:https://github.com/tylerchr/examples。效果如下:

启动服务访问 https://127.0.0.1:4430/index.html(我个人在页面加了些额外的东西):

golang 实现全双工通信

HTTP2是支持全双工通信的。这里需要注意的是,一般来说 HTTP2 server push 指的是,client 的一个请求,server 可以回复多个资源。但是全双工通信指的是,在一个已经建立的 tcp 连接中,基于 http2 的长连接及二进制分帧等设计。实现全双工通信。

实现,目前已实现,但是一些技术还需要更深的理解。

参考

重点

golang 实例github 仓库翻译

谷歌对http2的详细介绍:本文抄袭了极多

腾讯前端对http2的介绍,实际上和谷歌的介绍重合度很高

https://http2.github.io/faq/

如何验证网站是否是 HTTP2.0

关于http2:HTTP / 2是否会使websocke

非重点

nginx + golang server push

golang 的htt2 server push 的实现

golang 官方 h2 server push