Skip to content

[译]http2 #11

@wython

Description

@wython

概叙

http2有很多优点例如:

  1. 更高效的利用网络资源
  2. 通过压缩头部信息减少网络延迟
  3. 允许一个请求多通道传输 (多路复用)
  4. 主动向客户端推送信息
    http2是http1.1规范的另一个选择,不会废弃1.1,同时也保留http原有语法结构

1. 介绍

http使用很广泛。但是,http1.1也依然存在一些传输性能问题。
尤其是,http/1.0只允许一次tcp连接只能有一个未完成的请求。http/1.1加入了pipelining,不过也只是部分解决并发问题(到达的请求才能继续发送请求),依然有头阻塞(head-of-line blocking)问题。所以,http/1.0和http/1.1不得不通过多个和服务器的连接(这是指tcp连接)来发多个异步请求来减少网络延迟。

另外,http头部经常是重复而且冗余的,造成不必要的网络传输,也造成初始tcp堵塞窗口很快就满了。这导致一个新的tcp连接上发多个请求时,会有过度的延迟。

http/2解决这些问题通过定义了一个优化,通过http语法和底层连接的映射关系(HTTP/2 addresses these issues by defining an optimized mapping of HTTP's semantics to an underlying connection)。具体来说,http/2允许同一个连接交替发送和接受请求,使用更高效的编码http头部信息,允许设置优先级,高优先级的请求返回更快,从而提高性能。

最终协议更友好,相比1.x只需要更少的tcp连接。这意味着更好的利用网络宽带,给其他长连接和流的空间更大。

最后,http/2还允许更高效传输信息通过二进制信息帧。

2. HTTP/2协议概叙

http/2做了些优化,http/2支持所有1.1的核心特性,通过几个方面更高效。

协议的基本单元叫帧(frame)(4.1)。不同类型帧有不同的功能,例如,headers和data帧是http请求和相应的基础单元(8.1);其他帧类型像settings,window_update和push_promise用于其他http/2的新特性。

HTTP请求/响应通过自己单独的流传输实现了多路复用(5)。流是完全相互独立的,所以请求或者响应的阻塞或者延迟不会影响其他流的传输。

流量控制和优先级确保可以高效的使用多路复用的流。流量控制(5.2)确保了只有有效数据才会传输给接受者。优先级(5.3)确保有限的资源被重要的流先使用。

HTTP/2添加了一种新交互模式,服务器可以给客户端推送资源(8.2),交互一些网络的使用来避免潜在的网路延迟增长。服务器通过一个复用PUSH_PROMISE帧的合成请求实现这一点。于是,服务器可以在一个单独的流给这个合成请求发送一个响应。

因为HTTP连接头包含很多多余的信息,所以2.0压缩了头部(4.3)。这样有很多优势,可以允许多个请求塞到一个包里。

2.1. 文档组成

文档由四部分组成

  • Starting HTTP/2(3)覆盖http/2请求是怎么初始化的
  • The frame (4) 介绍HTTP/2帧是如何构成, stream (5)介绍了多路复用流细节
  • **Frame (6)error(7)**分别定义了帧的细节和http2中错误类型的使用
  • HTTP mappings (8) 和 **additional requirements (9)**介绍了帧和流如何用http的语法表达
    一些帧和流层的概念和http是分离的,这个规范不是为了定义一个完全通用的帧层。帧和流的引入主要是为了解决http协议需要和服务器推送

2.2. 约定和术语

略过

3 启动HTTP/2

一个http2连接是一个跑在由客户端发起的tcp连接上的应用层协议。
http/2 和1.1是一样的URI模版。http是80端口,https是443端口。访问处理像http://example.org/foohttps://example.com/bar 这样格式URI的请求,需要确保是否上游服务器是否支持http/2(上游服务器是指客户端建立连接直接接受数据的那一端)。

http2中使用http和https方式是不一样的。关于http URI的描述在第三章节,关于https URI的描述在第3.3章节。

3.1 HTTP/2版本标记

这个文档定义的协议游两个标志。

  • 字符串“h2”标记协议使用的是TLS( Transport Layer Security )。这个标记用在TLS-ALPN字段和所有被标记运行在tls的地方。
    “h2”字符串以0x68, 0x32这样两哥字符顺序序列化到ALPN协议中。

  • 字符串“h2c”标记http2运行在明文的TCP上。这个标记通常用于http/1.1升级头部字段和其他标记用于TCP上的地方。
    ALPN标记中保留了“h2c”字符串的空间,但是描述了一个不使用tls协议。

协商"h2" 或者 "h2c" 意味着使用文档中描述的这些传输、安全、帧和消息语义。

3.2 使用'http' URI 来启动HTTP/2

一个用'http'URI发请求的客户端,在不知道另一端是否支持http/2的情况下,使用HTTP Upgrade字段来说明([RFC7230]6.7章节)。客户端通过发送值为"h2c"标记的HTTP Upgrade 头部请求来完成。这样的请求 ** 必须(MUST) ** 正好包含一个 HTTP2-Settings(3.2.1) 头字段。
例如:

GET / HTTP/1.1
Host: server.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>

在客户端能发HTTP/2帧之前,这个包含payload body的请求必须完全发完。这意味着大请求可能阻塞连接直到完全发完为止。

如果初始请求和后续请求的并发很重要,那么可以使用一个OPTIONS请求作为升级HTTP/2的预检,不过需要额外的往返消耗。

不支持HTTP/2的服务器可以直接响应,就像没有Upgrade头部字段一样。

HTTP/1.1 200 OK
Content-Length: 243
Content-Type: text/html

...

服务器必须忽略"h2"。使用"h2"标记说明HTTP/2加TLS, 这会在 章节3.3 介绍。

服务器支持HTTP/2通过101(切换协议)状态码返回。101响应隔着一个空行,然后服务器开始发HTTP/2帧。这些帧**必须(MUST)**响应初始升级的那个请求的。
例如:

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c

[ HTTP/2 connection ...

服务器发送的第一个HTTP/2帧必须是由SETTINGS帧(章节6.5)组成的连接序言(章节3.5)。收到101响应后,客户端也**必须(MUST)**发一个包含SETTINGS帧(章节6.5)的连接序言(章节3.5)。

之前的HTTP/1.1升级请求会被分配一个流1(看章节5.1.1)标志和一个默认的优先级值(章节5.3.5)。流1以"半关闭"状态单向由客户端到服务端(看章节5.1),直到HTTP/1.1完全完成。完成HTTP/2升级之后,响应也能使用流1。

3.2.1 HTTP2-Settings 头字段

从HTTP/1.1升级到HTTP/2的请求**必须(MUST)**有且只有一个HTTP2-Settings 头字段。HTTP/2头字段是一个包含HTTP/2连接参数的连接-管理字段,在服务器也可以提升之前提供。

HTTP2-Settings    = token68

如果这个头字段没有提供,或者超过一个,服务器都**不准(MUST NOT)升级到HTTP2连接。服务器也不准(MUST NOT)**发这个头部字段。

HTTP2-Settings 头字段都内容是SETTINGS帧(章节6.5)的payload,使用base64url字符串编码(这是一种忽略尾部'='字符的URL- 和文件名-安全 Base64编码,在[RFC4648]章节5有介绍),token68的ABNF[RFC5234]生成方式在[RFC7235]章节2.1定义。

由于HTTP/2升级是即时连接,因此发送HTTP2-Settings头字段的客户端必须发送HTTP2-Settings作为Connect头字段的连接选项来防止被转发(看[RFC7230]章节6.1

服务器解码和解释这些值就像其他SETTING帧一样。没有必要清楚的确定这些设置(章节 6.5.3),因为101返回已经说明。在升级请求里面提供这些值,这样客户端才可以接受其他服务器帧之前提供参数。

提前支持HTTP2的情况下启动HTTP/2

客户端有其他办法知道特定服务器是不是支持HTTP/2。例如,[ALT-SVC]介绍了发布此功能的机制。
客户端必须发送一个连接序言(章节3.5)然后才可以立即发送这样HTTP/2帧给这样的服务器;通过这样一个连接序言服务器可以识别这些连接。这只适用于纯tcp连接上建立HTTP2连接,在TLS上建立HTTP2连接**必须(MUST)**使用TLS里的协议协商[TLS-ALPN]

同样,服务器也**必须(MUST)**发送一个连接序言(章节3.5)。

如果没有其他额外信息,提前知道支持HTTP/2也不是一个明确的信号表示服务器会在将来的连接也支持HTTP/2。比如,服务器的配置被改变,集群不同实例之间的配置可能不同,或者网络状态可能被更改。

参考资料

HTTP2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions