HTTP2新特性

1、发展历程

HTTP2新特性_第1张图片

HTTP/0.9:

  • 只有一个命令 GET
  • 没有HEADER等描述数据的信息
  • 服务器发送完毕内容,就关闭TCP连接。一个HTTP事务要使用一个TCP连接。 

HTTP/1.0:

  • 增加了很多命令
  • 增加了status code (描述服务端处理请求的状态的)和 header
  • 多字符集支持、多部分发送、权限、缓存等
  • 缺陷:
    • 第一点是: 连接无法实现真正意义上的复用(Connection :keep-Alive,默认false)
    • 第二点是: Head-Of-Line Blocking(HOLB,队头/线头/头部阻塞) 

 HTTP/1.1

  • 持久连接/长连接
  • pipeline管道化技术
  • 头部增加Host

SPDY

HTTP2新特性_第2张图片

        SPDY 没有完全改写 HTTP 协议,而是在 TCP/IP 的应用层与运输层之 间通过新加会话层的形式运作。同时考虑到安全性问题,SPDY 规定通信中使用 SSL。SPDY 以会话层的形式加入,控制对数据的流动,但还是采用 HTTP 建立通信连接,改层工作在SSL层之上、HTTP层之下。 

  • 二进制分帧
  • 首部压缩(Header Compression)
  • 多路复用
  • 对请求划分优先级
  • 服务器推送流(即Server Push技术)

HTTP/2

  • 二进制分帧
  • 首部压缩(Header Compression)
  • 多路复用
  • 对请求划分优先级
  • 服务器推送流(即Server Push技术) 

HTTP Working-Group 以 SPDY/2 为基础,开发 HTTP/2。但是,HTTP/2跟 SPDY 仍有不同的地方,主要是以下两点:

  1. HTTP/2 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS
  2. HTTP/2 消息头的压缩算法采用 HPACK,而非 SPDY 采用的 DEFLATE

2、二进制分帧(frame)

HTTP2.0性能增强的核心:二进制分帧。

        HTTP 2.0最大的特点: 不会改动HTTP 的语义,HTTP 方法、状态码、URI 及首部字段,等等这些核心概念上一如往常,却能致力于突破上一代标准的性能限制,改进传输性能,实现低延迟和高吞吐量。而之所以叫2.0,是在于新增的二进制分帧层。

        在二进制分帧层上,HTTP 2.0 会将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码 ,其中HTTP1.x的首部信息会被封装到Headers帧,而我们的request body则封装到Data帧里面。帧是数据传输的最小单位,以二进制传输代替原本的明文传输。

HTTP2新特性_第3张图片

        HTTP 2.0 所有的通信都在一个连接(TCP连接)上完成,这个连接可以承载任意数量的双向数据流。相应地,每个数据流以消息的形式发送,而消息由一或多个帧组成,这些帧可以乱序发送,然后再根据每个帧首部的流标识符重新组装。 

        HTTP性能的关键在于低延迟而不是高带宽!大多数HTTP 连接的时间都很短,而且是突发性的,但TCP 只在长时间连接传输大块数据时效率才最高。HTTP 2.0 通过让所有数据流共用同一个连接,可以更有效地使用TCP 连接,让高带宽也能真正的服务于HTTP的性能提升。

单连接多资源方式的好处:

  • 可以减少服务连接压力,内存占用少了,连接吞吐量大了
  • 由于 TCP 连接减少而使网络拥塞状况得以改观;
  • 慢启动时间减少,拥塞和丢包恢复速度更快。

HTTP/2 的四个概念: 

  • Connection :1 个 TCP 连接,包含 1 个或者多个 stream。所有通信都在一个 TCP 连接上完成,此连接可以承载任意数量的双向数据流。
  • Stream:一个双向通信的数据流,包含 1 条或者多条 Message。每个数据流都有一个唯一的标识符和可选的优先级信息,用于承载双向消息。流是连接中的一个虚拟信道,可以承载双向消息传输。每个流有唯一整数标识符。为了防止两端流ID冲突,客户端发起的流具有奇数ID,服务器端发起的流具有偶数ID。
  • Message:消息是指逻辑上的HTTP消息(请求/响应)。一系列数据帧组成了一个完整的消息。比如一系列DATA帧和一个HEADERS帧组成了请求消息。
  • Frame:最小通信单位,以二进制压缩格式存放内容。来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装。

HTTP2新特性_第4张图片

Frame 由 Frame Header 和 Frame Payload 两部分组成。所有帧都以固定的 9字节大小的头作为帧开始,后跟可变长度的有效载荷 payload。 

HTTP2新特性_第5张图片

帧头的字段定义如下:

  • Length:帧有效负载的长度(数据的长度,不包含头部),注意:帧头的 9 个八位字节不包含在此长度值中。
  • Type:这 8 位用来表示帧类型的。帧类型确定帧的格式和语义。实现方必须忽略并丢弃任何类型未知的帧。 

DATA: 用于传输HTTP消息体
HEADERS:用户传输关于流的额外的首部字段
PRIORITY:用户指定或者重新指定引用资源的优先级
RST_STRING:用于通知流的非正常终止
SETTINGS:用于通知两端通信方式的数据配置
PUSH_PROMISE:用于发出创建流和服务器引用资源的要约
PING:用于计算往返时间,执行“活性”检查
GOAWAY:用于通知对端停止在当前连接的创建流
WINDOW_UPDATE:用于针对个别流或个别连接实现流量控制
CONTINUATION:用于继续一系列首部块片段 

Flags:标志位,常用的标志位有 END_HEADERS 表示头数据结束,相当于 HTTP/1里头后的空行(“\r\n”)。 

R:保留的 1 位。该位的语义未定义,发送时必须保持未设置 (0x0),接收时必须忽略。

Stream Identifier:流标识符,表示为无符号 31 位整数。由客户端发起的流必须使用奇数编号的流标识符;那些由服务器发起的必须使用偶数编号的流标识符。DATA 帧必须与某一个流相互关联。

stream ID 的作用:
实现多路复用的关键。接收端的实现可以根据这个 ID 并发、组装消息。同一个 stream 内 frame 必须是有序的。

HTTP2新特性_第6张图片

推送依赖性请求的关键。客户端发起的流是奇数编号,服务端发起的流是偶数编号。 

HTTP2新特性_第7张图片

3、头部压缩(HPACK)

为什么要压缩?

        在 HTTP/1 中,HTTP 请求和响应都是由「状态行、请求 / 响应头部、消息主体」三部分组成。一般而言,消息主体都会经过 gzip 压缩,或者本身传输的就是压缩过后的二进制文件(例如图片、音频),但状态行和头部却没有经过任何压缩,直接以纯文本传输。 

        根据 HTTP Archive 的统计,当前平均每个页面都会产生上百个请求。越来越多的请求导致消耗在头部的流量越来越多,尤其是每次都要传输 UserAgent、Cookie 这类不会频繁变动的内容,完全是一种浪费。

        以下是我随手打开的一个页面的抓包结果。可以看到,传输头部的网络开销超过 100kb,比 HTML 还多:

HTTP2新特性_第8张图片

        HTTP/2协议中定义了 HPACK,这是一种新的压缩方法,它消除了多余的header 字段,将漏洞限制到已知的安全攻击,并且在受限的环境中具有有限的内存需求。HPACK 格式特意被设计成简单且不灵活的形式:两种特性都降低了由于实现错误而引起的互操作性或安全性问题的风险;没有定义扩展机制,只能通过定义完整的替换来更改格式。

需要注意的是,http 2.0关注的是首部压缩,而我们常用的gzip等是报文内容(body)的压缩,二者不仅不冲突,且能够一起达到更好的压缩效果。 

如何进行头部压缩

简单说,HPACK头部压缩需要在支持 HTTP/2 的浏览器和服务端之间:

  • 维护一份相同的静态表(Static Table),包含常见的头部名称,以及常见的头部名称与值的组合(静态表内容共61项,索引号1-61);
  • 维护一份相同的动态表(Dynamic Table),当一个header name 或者header value在静态表中不存在,会被插入动态表中,可以动态地添加内容(动态表索引从62开始);
    • 客户端和服务端会共同维护一份动态表
    • 第一次发送的时候需要明文发送(要经过Huffman编码),第二次及第N次发送索引号
  • 对不存在的头部使用哈夫曼编码(Huffman Coding),并动态缓存到索引(动态表)

HTTP2新特性_第9张图片

HTTP2新特性_第10张图片

静态表 

一个预定义且不可更改的 header 字段列表。先定义好的内容,只有固定的几十个值,如果要发送的值符合静态表时,用对应的 Index 替换即可,这样就大大压缩了头部的大小,如果遇到不在静态表中的值,就会用到动态表。

HTTP2新特性_第11张图片

 一共有61个,这里只写了部分

HTTP2新特性_第12张图片

动态索引 

HTTP2新特性_第13张图片

  • 动态表是一个由先进先出的队列维护的有空间限制的表,同样维护的是头部与对应的索引。
  • 每个动态表只针对一个连接(TCP),每个连接的压缩解压缩的上下文有且仅有一个动态表。
  • 那么动态表就是,当一个头部没有出现过的时候,会把他插入动态表中,索引从62开始。 

4、多路复用(Multiplexing)

        http1.1中,浏览器客户端在同一时间,针对同一域名下的请求有一定数量的限制,超过限制数目的请求会被阻塞。这也是为何一些站点会有多个静态资源CDN 域名的原因之一。 

HTTP2新特性_第14张图片

        http 2.0 连接都是持久化的,而且客户端与服务器之间也只需要一个连接(每个域名一个连接)即可。http2连接可以承载数十或数百个流的复用,多路复用意味着来自很多流的数据包能够混合在一起通过同样连接传输。当到达终点时,再根据不同帧首部的流标识符重新连接将不同的数据流进行组装。 

HTTP2新特性_第15张图片

        websocket 原生协议由于没有这个 stream ID 类似的字段,所以它原生不支持多路复用。在同一个 stream 内部的 frame 由于没有其他的 ID 编号了,所以无法乱序,必须有序,无法并发。 

  • 单个 HTTP/2 连接可以包含多个并发打开的 stream 流,任一一个端点都可能交叉收到来自多个 stream 流的帧。
  • stream 流可以单方面建立和使用,也可以由客户端或服务器共享。
  • 任何一个端都可以关闭 stream 流。
  • 在 stream 流上发送帧的顺序非常重要。收件人按照收到的顺序处理帧。特别是,HEADERS 和 DATA 帧的顺序在语义上是重要的。
  • stream 流由整数标识。stream 流标识符是由发起流的端点分配给 stream流的。

5、服务器推送(Server Push)

        服务器可以对一个客户端请求发送多个响应,服务器向客户端推送资源无需客户端明确地请求。并且,服务端推送能把客户端所需要的资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。 

        正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。Server Push 让 http1.x 时代使用内嵌资源的优化手段变得没有意义;如果一个请求是由你的主页发起的,服务器很可能会响应主页内容、logo 以及样式表,因为它知道客户端会用到这些东西,这相当于在一个HTML 文档内集合了所有的资源。

        不过与之相比,服务器推送还有一个很大的优势:可以缓存!也让在遵循同源的情况下,不同页面之间可以共享缓存资源成为可能。

HTTP2新特性_第16张图片

注意两点:

  • 推送遵循同源策略;
  • 这种服务端的推送是基于客户端的请求响应来确定的。 

        当服务端需要主动推送某个资源时,便会发送一个 Frame Type 为PUSH_PROMISE 的 Frame,里面带了 PUSH 需要新建的 Stream ID。意思是告诉客户端:接下来我要用这个 ID 向你发送东西,客户端准备好接着。客户端解析 Frame 时,发现它是一个 PUSH_PROMISE 类型,便会准备接收服务端要推送的流。

6、http2.0性能瓶颈

        启用http2.0后会给性能带来很大的提升,但同时也会带来新的性能瓶颈。因为现在所有的压力集中在底层一个TCP连接之上,TCP很可能就是下一个性能瓶颈,比如单个TCP packet丢失导致整个连接阻塞,无法逃避,此时所有消息都会受到影响。

HTTP2新特性_第17张图片

 

7、安全风险

  • 窃听风险:通信使用明文,明文报文不具备保密性,内容可能被窃听
  • 冒充风险:不验证通信方的身份(不进行身份验证),有可能遇到伪装
  • 篡改风险:无法证明报文的完整性,有可能已遭篡改

你可能感兴趣的:(web知识,服务器,运维,http)