(二) HTTP/2起步

与HTTP1.x一样,HTTP/2仍然是建立在TCP连接之上的应用层协议,请求由客户端发起,并且,URI的基本规则保持不变。

HTTP/2的版本标识

对应URI中的http或https,HTTP/2有2个版本标识:

  • “h2”对应以”https”开头的URI,表示HTTP/2是运行在TLS之上的,由TLS提供认证和加密等安全保障;
  • “h2c”对应以”http”开头的URI,表示HTTP/2是运行在明文TCP之上的。

HTTP1.1连接“升级”到HTTP/2

如果客户端无法确定服务端是否支持HTTP/2,那么,客户端需要利用HTTP1.1的“升级”机制来发起请求。在请求报文中需要包含一个Upgrade报头字段,除此之外,必须包含一个HTTP2-Settings报头字段。例如:

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的帧之前全部发送出去,这意味着一个较大的请求会阻塞TCP连接的使用,直到全部内容发送完毕。

如果多个请求的并发是重要的,也就是说,希望最大限度地做到多个请求的并发,那么,可以利用HTTP1.1的OPTIONS请求作为初始请求来“升级”到HTTP/2。原因是OPTIONS请求的体积较小,它阻塞TCP连接的时间也就较短,后续的各个请求就可以并发发送了。代价是额外耗费了一个OPTIONS请求的往返成本。

不支持HTTP/2的服务端会直接忽略Upgrade头域,返回一个HTTP1.1的200响应,例如:

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

...

如果Upgrade的值不是”h2c”而是”h2”,那么,服务端也会直接忽略掉它。

支持HTTP/2的服务端会接受“升级”并返回一个HTTP1.1的101响应。在终止101响应的空行之后,服务端就可以发送HTTP/2的帧了。这些帧必须包含对发起“升级”请求的响应。例如:

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

[ HTTP/2 connection ...

服务端发送的第一个HTTP/2帧必须是一个包含SETTINGS帧 的服务端连接序言。客户端在收到101响应后必须也发送一个包含SETTINGS帧的连接序言。

客户端在“升级”成功之前发送的HTTP1.1请求会被分配一个值为1的“流”标识,并被赋予默认的优先级。

前面提到,一个请求从HTTP1.1升级到HTTP/2,必须显式地包含HTTP2-Settings报头字段。HTTP2-Settings是一个连接相关的报头字段,包含管理HTTP/2连接的参数,期待着服务端会接受升级请求。
如果请求中没有HTTP2-Settings或者有多个HTTP2-Settings,服务端都会拒绝升级。另外,服务端不能发送HTTP2-Settings报头。HTTP2-Settings报头的内容是SETTINGS帧的有效载荷,使用base64url编码。

因为升级只是意欲应用在当前的连接,所以客户端除了发送HTTP2-Settings报头外,还必须将”HTTP2-Settings”作为一个连接选项放到Connection报头中,以达到阻止转发到下一跳的目的。(这里的一跳指的是HTTP连接的一跳,而非IP路由的一跳)

开始一个HTTP/2的https请求

客户端通过使用TLS的应用层协议协商扩展(TLS-ALPN)来发起请求。

在TLS之上的HTTP/2使用”h2”标识,而不能使用”h2c”标识。

一旦TLS协商完成,客户端和服务端都必须发送一个连接序言。

预先知道的情况下开始HTTP/2请求

客户端可以通过其它方式判断某个服务端是否支持HTTP/2。例如,ALT-SVC描述了一种公告这种能力的机制。

对于支持HTTP/2的服务端,客户端必须发送连接序言,然后可以立即发送HTTP/2的帧。服务端可以通过连接序言识别这些连接。这只影响基于明文TCP的HTTP/2连接的建立;基于TLS的HTTP/2实现必须使用TLS的协议协商(TLS-ALPN)。类似地,服务端也必须发送一个连接序言。

在没有更多信息的情况下,先前对HTTP/2的支持并不表明一个服务端在以后的连接中一定支持HTTP/2。例如,服务器的配置可能会改变,或者一个集群中不同服务器的配置可能有差异,或者随网络条件而变化。

HTTP/2连接序言

在HTTP/2中,每个端点都被要求发送一个连接序言,其作用是:

  • 作为正在使用的协议的最终确认;
  • 为HTTP/2连接建立初始设置。

客户端和服务端各自发送一个不同的连接序言。

客户端的连接序言以一个24字节的序列开始,其十六进制表示是:

0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a

其字符串表示是:

PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n)

这个序列之后必须是一个SETTINGS帧(可以是空帧)。客户端在收到101响应后立即发送客户端连接序言,或者将连接序言作为TLS连接的第一组应用数据字节。如果在预先知道服务端支持HTTP/2的情况下发起HTTP/2连接,客户端连接序言在连接建立后发送。

客户端连接序言是被特意选择的,目的是使大部分服务端和中间代理不尝试进一步处理其后的帧。

服务端连接序言包含一个有可能为空的SETTINGS帧,它必须是服务端在HTTP/2上发送的第一个帧。

作为连接序言的一部分,来自对端的SETTINGS帧必须在发送本端连接序言之后加以确认。

为了避免不必要的延迟,允许客户端在发送客户端连接序言之后立即发送额外的帧,不需要等待接收服务端的连接序言。然而,需要注意的是,服务端连接序言的SETTINGS帧中可能包含期望客户端如何与服务端通信的必要参数修改。在接收到SETTINGS帧之后,客户端应该尊敬建立的全部参数。在一些配置中,服务端可以在客户端发送额外的帧之前传送SETTINGS帧,从而提供了一个避免这种问题的机会。

客户端和服务端都必须将无效的连接序言视为一种类型是PROTOCOL_ERROR的连接错误,在这种情况下,可以发送一个GOAWAY帧,因为一个无效的连接序言表明对端没有使用HTTP/2协议。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值