Nginx同时支持spdy和http2

Posted 腾讯课堂Coding学院

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nginx同时支持spdy和http2相关的知识,希望对你有一定的参考价值。

来源 / Coding学院(ID:ke_coding)

1
HTTP1.X协议存在的不足

距离HTTP 成为如今互联网最流行的协议已经过去很长时间了,随着现在 WEB 技术的飞速发展尤其是 html5 的不断演进,以及当前网络环境的改变、传输内容的变化,当初的 HTTP 规范已经逐渐无法满足人们的需要求。

HTTP1.x的最大弊端就是每个 TCP 连接同一时间只能对应一个 HTTP 请求,即每个 HTTP 连接只请求一个资源,浏览器只能通过建立多个连接来解决。此外在 HTTP 1.1中对请求是严格的先入先出(FIFO)进行的,如果中间某个请求处理时间较长会阻塞后面的请求。HTTP 头在同一个会话里是反复发送的,中间的冗余信息,比如 User-Agent、Host 等不需要重复发送的信息也在反复发送,浪费带宽和资源。

2
SPDY与HTTP2

作为WWW的基础协议,HTTP的重要性不言而喻。但是自从1999年HTTP 1.1获采用以来,虽然其间也推出过10多个草案版本,但是由于这些版本在各方面(尤其是性能方面)被认为仍有改进空间,这个基础协议一直未进行任何重大升级。2012年,Google推出了基于TCP的应用层协议SPDY(取speedy谐音,意为更快),该协议基本沿用了HTTP的语义表示,同时在性能上进行了大幅改进,以减少连接数为目的,通过压缩、多路复用以及优先级赋权来缩短网页的加载时间,同时提高了安全性。总的来说,SPDY主要有以下有点:

(1)多路复用 请求优化

SPDY 规定在一个 SPDY 连接内可以有无限个并行请求,即允许多个并发 HTTP 请求共用一个 TCP会话。这样 SPDY 通过复用在单个 TCP 连接上的多次请求,而非为每个请求单独开放连接,这样只需建立一个 TCP 连接就可以传送网页上所有资源,不仅可以减少消息交互往返的时间还可以避免创建新连接造成的延迟,使得 TCP 的效率更高。

此外,SPDY 的多路复用可以设置优先级,而不像传统 HTTP 那样严格按照先入先出一个一个处理请求,它会选择性的先传输 CSS 这样更重要的资源,然后再传输网站图标之类不太重要的资源,可以避免让非关键资源占用网络通道的问题,提升 TCP 的性能。

(2)支持服务器推送技术

服务器可以主动向客户端发起通信向客户端推送数据,这种预加载可以使用户一直保持一个快速的网络。

(3)SPDY 压缩了 HTTP 头

舍弃掉了不必要的头信息,经过压缩之后可以节省多余数据传输所带来的等待时间和带宽。

(4)强制使用 SSL 传输协议

Google 认为 Web 未来的发展方向必定是安全的网络连接,全部请求 SSL 加密后,信息传输更加安全。

HTTP/2,是HTTP协议自1999年HTTP 1.1发布后的首个更新,主要基于SPDY协议。HTTP/2基于SPDY的,主要差别是:

(1)增加了HTTP/1.1 Upgrade的机制,可在TCP上直接使用HTTP/2,不像SPDY那样必须在TLS上。

(2)更完善的协议商讨和确认流程。

(3)更完善的Server Push流程。

(4)增加控制帧的种类,并对帧格式考虑得更细致。

(5)有新算法HPACK专门压缩SPDY header block。

(6)HTTP/2文档带有一些示例和详细说明,这是SPDY没有的。

nginx作为一款高性能web服务器,目前广泛应用于互联网中,NGINX在支持SPDY和HTTP2上都做了不少工作。NGINX在1.9.5之前,支持SPDY协议,在1.9.5之后,NGINX添加了对HTTP2协议的支持。可是,在支持HTTP2的同时,NGINX去掉了对SPDY的支持。

这就存在一个问题:如果希望NGINX支持SPDY,则需要使用1.9.5之前的版本,如果希望NGINX支持HTTP2,则使用1.9.5之后的版本。HTTP/2作为SPDY的替代者,很多人肯定认为已经没有必要支持SPDY,但是实际情况如何呢?从线上实际使用数据来看,目前使用SPDY协议的客户端仍然占了相当大的比例,甚至超过了HTTP/2。SPDY和HTTP/2共存的时间仍然会持续一段时间。可是如果支持SPDY,就必须要放弃HTTP/2,并且NGINX新版本的特性都无法使用。那么,如何解决这个问题呢?

Nginx同时支持spdy和http2

3
NPN协议和ALPN协议

为了解决NGINX同时支持SPDY和HTTP/2,我们首先需要了解NPN协议和ALPN协议。

NPN简单来说就是在TLS的握手阶段增加一些字段来表明服务器端和客户端希望在TLS基础上使用HTTP之外的(SPDY)协议。NPN同样是Google提出的,为SPDY铺路。

随着 SPDY 被 HTTP/2 取代,NPN 也被修订为 ALPN(Application Layer Protocol Negotiation,应用层协议协商)。二者目标一致,但实现细节不一样。以下是它们主要差别:

NPN 是服务端发送所支持的 HTTP 协议列表,由客户端选择,而 ALPN 是客户端发送所支持的 HTTP 协议列表,由服务端选择。NPN的协商结果是在 Change Cipher Spec 之后加密发送给服务端,而ALPN的协商结果是通过 Server Hello 明文发给客户端。下面是SSL握手时抓包的ALPN与NPN内容:Nginx同时支持spdy和http2Nginx同时支持spdy和http2

4
NGINX同事支持SPDY和HTTP2

HTTP/2和SPDY都是基于SSL基础之上。在SSL握手之中,协商实际的应用层协议。

Nginx同时支持spdy和http2

SSL的握手其实主要做的事情就是身份认证和密钥协商。关于SSL握手的详细细节,这里就不多介绍。需要注意的是,客户端在SSL握手之初,发送client hello给服务端,同时会带很多扩展信息:

Nginx同时支持spdy和http2

其中就包含NPN的扩展和ALPN的扩展。客户端带有支持的协议内容和顺序, 发送给服务端。如果双方都支持ALPN协议,则服务端会根据客户端的支持的协议和服务端支持的协议进行协商,然后将协商后的协议在server hello阶段发送给客户端。SSL握手完成后,客户端根据协商的协议与服务端通信。NPN协议其实跟ALPN协议差不多,只是协商由客户端处理,并将协商结果在Change Cipher Spec阶段发送给服务端。

既然知道了原理,NGINX同时支持SPDY和HTTP/2就不难了。由于NGINX的SPDY模块和HTTP/2模块的代码主体基本已经实现,因此,在实际处理过程中,只需要修改NGINX中对NPN协议和ALPN协议的相关处理,优先支持HTTP/2,再支持SPDY。在NPN的协商过程中,NGINX返回顺序HTTP/2,SPDY,HTTP,让客户端协商协议。而在ALPN的协议协商中,NGINX根据客户端的协议支持,匹配客户端协议列表,进行协议协商。当SSL握手完成时,客户端和服务器就会使用协商好的协议进行数据传输。当然,NGINX 需要在配置本身在同时支持SPDY和HTTP/2上也需要稍作修改。

因此,实现了同时支持SPDY和HTTP2后,服务端同时支持SPDY和HTTP/2,协议协商会根据客户端的支持情况动态的选择SPDY和HTTP2,并且优先选择HTTP/2。

Nginx同时支持spdy和http2

只要去做,

总有可能。

先转发,再点二维码,

就是对我们最好的支持!


业界最顶尖的技术大咖/最权威的实战分享/最前沿的行业资讯/尽在腾讯课堂Coding学院

长按二维码关注Coding学院

以上是关于Nginx同时支持spdy和http2的主要内容,如果未能解决你的问题,请参考以下文章

当支持 SPDY 的浏览器收到 HTTP2 (H2) 响应时会发生啥?

Ghost+Nginx部署HTTP2

记录nginx启用http2后不生效的问题

Nginx 1.10 上的 SPDY 代替 HTTP2

netty系列之:让TLS支持http2

Jetty HTTP2 服务器推送支持