Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[译]http2 #11

Open
Open
@wython

Description

概叙

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

        AltStyle によって変換されたページ (->オリジナル) /