2016年,HTTP/2正式成为标准,越来越多的网站开始支持HTTP/2。

相比HTTP/1.1,HTTP/2在性能上有了巨大的提升。支持多路复用、头部压缩、服务器推送等新特性,能大幅减少页面加载时间,提升用户体验。

最近我把自己的博客从HTTP/1.1升级到了HTTP/2,配置很简单,但是性能提升很明显。今天就来聊聊HTTP/2的入门知识,以及如何在Nginx上配置HTTP/2。

一、HTTP/1.1的痛点

在聊HTTP/2之前,先说说HTTP/1.1的痛点。

HTTP/1.1是1999年发布的标准,至今已经使用了十几年。在这十几年里,Web发生了翻天覆地的变化,从简单的文本页面变成了复杂的富应用,页面资源越来越多,加载越来越慢。

HTTP/1.1主要有以下几个痛点:

1. 队头阻塞

HTTP/1.1是基于请求-响应模型的,同一个TCP连接上,一次只能处理一个请求。如果第一个请求很慢,后面的请求都要等着,这就是"队头阻塞"。

虽然HTTP/1.1支持持久连接(Keep-Alive),可以在一个TCP连接上发送多个请求,但是请求必须是串行的,一个接一个地发送,不能并行。

为了解决这个问题,浏览器通常会对同一个域名建立多个TCP连接(一般是6个),并行发送请求。但是建立多个TCP连接有额外的开销,而且连接数有限,还是不能完全解决队头阻塞的问题。

2. 头部冗余

HTTP/1.1的头部是文本格式的,每次请求都要发送完整的头部信息,包括User-Agent、Cookie、Accept等。这些头部信息很多都是重复的,每次请求都要发送一遍,浪费带宽。

特别是Cookie,有时候Cookie很大,每次请求都要带上,很浪费带宽。

3. 不支持服务器推送

HTTP/1.1不支持服务器主动推送资源。浏览器请求一个HTML页面,服务器只返回HTML,浏览器解析HTML后发现需要CSS、JS、图片等资源,再分别发送请求获取这些资源。这一来一回,增加了页面加载时间。

如果服务器能主动把HTML需要的CSS、JS等资源推送给浏览器,就能减少请求次数,加快页面加载。

二、HTTP/2的核心特性

HTTP/2就是为了解决HTTP/1.1的这些痛点而设计的。它的核心特性包括:

1. 二进制分帧

HTTP/2采用二进制格式传输数据,而不是HTTP/1.1的文本格式。二进制格式解析更高效,更紧凑。

HTTP/2把所有传输的数据都分割成更小的消息和帧,每个帧都有帧类型、长度、流标识等字段。不同的帧可以交错传输,接收方根据流标识重新组装。

这是HTTP/2其他特性的基础。

2. 多路复用

多路复用是HTTP/2最重要的特性。它允许在一个TCP连接上同时发送多个请求和响应,不用等待前面的请求完成。

每个请求都有一个唯一的流标识,不同流的帧可以交错传输,接收方根据流标识把帧重新组装成完整的请求或响应。

这样就彻底解决了HTTP/1.1的队头阻塞问题,一个TCP连接就能并行处理多个请求,不需要建立多个TCP连接,减少了连接开销,也提高了带宽利用率。

3. 头部压缩HPACK

HTTP/2使用HPACK算法对头部进行压缩,减少头部传输的大小。

HPACK使用静态表和动态表来存储常用的头部字段,传输的时候只需要发送索引,不需要发送完整的头部内容。而且动态表会在连接过程中不断更新,后续相同的头部只需要发送索引即可。

这样就能大幅减少头部传输的大小,节省带宽,特别是对于Cookie很大的网站,效果更明显。

4. 服务器推送

HTTP/2支持服务器主动推送资源。浏览器请求一个HTML页面,服务器可以主动把这个页面需要的CSS、JS、图片等资源推送给浏览器,浏览器不需要再分别发送请求获取这些资源。

这样就能减少请求次数,加快页面加载速度。特别是对于首次访问的用户,效果很明显。

不过服务器推送需要谨慎使用,如果推送的资源浏览器已经缓存了,反而会浪费带宽。所以一般只推送关键的、未缓存的资源。

三、HTTP/2的其他特性

除了上面的核心特性,HTTP/2还有一些其他特性:

1. 流量控制

HTTP/2支持流量控制,每个流都可以独立控制流量,防止发送方发送太快,接收方处理不过来。

2. 优先级

HTTP/2支持设置请求的优先级,重要的资源(比如HTML、CSS)可以设置更高的优先级,优先传输,加快页面渲染。

3. 重置流

HTTP/2支持重置流,如果一个请求不需要了,可以发送RST_STREAM帧取消这个流,不用关闭整个TCP连接。这在HTTP/1.1里是做不到的,只能关闭连接。

4. 更安全

虽然HTTP/2标准本身不强制要求加密,但是目前所有主流浏览器都只支持基于TLS加密的HTTP/2(也就是h2)。所以使用HTTP/2的网站一般都是HTTPS的,更安全。

四、Nginx配置HTTP/2实战

说了这么多理论,来看看实际怎么配置。我用的是Nginx,配置HTTP/2很简单。

1. 确认Nginx版本

首先确认Nginx版本是否支持HTTP/2。Nginx从1.9.5版本开始支持HTTP/2,建议使用1.10以上的稳定版本。

可以用nginx -v查看版本。

2. 确认OpenSSL版本

HTTP/2需要OpenSSL 1.0.2以上版本,因为需要支持ALPN(应用层协议协商)。可以用openssl version查看版本。

3. 配置SSL证书

因为浏览器只支持加密的HTTP/2,所以需要先配置好SSL证书。可以用Let's Encrypt免费证书,或者购买商业证书。

配置SSL的示例:

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    # 其他SSL配置...
}

注意listen 443 ssl http2;这一行,加上http2就开启了HTTP/2支持。就是这么简单!

4. 优化HTTP/2配置

除了基本的开启,还可以做一些优化:

# HTTP/2最大并发流数
http2_max_concurrent_streams 128;

# HTTP/2窗口大小
http2_recv_buffer_size 256k;

# 服务器推送(可选)
location = /index.html {
    http2_push /style.css;
    http2_push /script.js;
}

5. 重启Nginx

配置完成后,重启Nginx:nginx -s reload

6. 验证是否生效

可以用浏览器开发者工具查看,在Network面板里,Protocol列会显示h2,说明HTTP/2已经生效。

也可以用在线工具检测,比如https://tools.keycdn.com/http2-test。

五、浏览器兼容性

HTTP/2的浏览器兼容性已经很好了。目前所有主流浏览器的最新版本都支持HTTP/2,包括Chrome、Firefox、Safari、Edge等。

根据caniuse.com的数据,全球约88%的用户使用的浏览器支持HTTP/2。对于不支持HTTP/2的浏览器,Nginx会自动降级到HTTP/1.1,不会有兼容性问题。

所以现在升级到HTTP/2是很安全的,支持的用户能享受更快的速度,不支持的用户也不受影响。

六、性能测试对比

我把自己的博客升级到HTTP/2之后,做了一个简单的性能测试对比。

测试页面是博客首页,包含1个HTML、2个CSS、3个JS、10张图片,总共16个资源。

测试条件:Chrome浏览器,清空缓存,网络限速为Fast 3G(下载1.6Mbps,上传750Kbps,延迟150ms)。

测试结果:

指标HTTP/1.1HTTP/2提升
页面加载时间3.2秒1.8秒43.8%
DOMContentLoaded1.5秒0.9秒40%
请求数1616-
下载大小450KB420KB6.7%

可以看到,HTTP/2的页面加载时间比HTTP/1.1快了近44%,效果很明显。主要是因为多路复用减少了请求等待时间,头部压缩减少了传输大小。

在更快的网络环境下,提升可能没有这么明显,但是在慢网络(比如移动网络)下,提升会更明显。

七、注意事项

升级HTTP/2有几个注意事项:

1. 必须使用HTTPS

如前所述,浏览器只支持加密的HTTP/2,所以必须先配置好HTTPS。如果你的网站还在用HTTP,需要先升级到HTTPS。

2. 域名分片不再需要

在HTTP/1.1时代,为了突破浏览器的连接数限制,很多网站会把资源分散到多个域名(域名分片)。但是在HTTP/2里,一个连接就能并行处理多个请求,域名分片反而会增加连接开销,所以不再需要域名分片。

3. 资源合并不再必要

在HTTP/1.1时代,为了减少请求数,会把多个CSS、JS合并成一个文件。但是在HTTP/2里,请求的开销很小,合并文件反而可能导致缓存失效(改一个小地方就要重新下载整个大文件)。所以在HTTP/2里,可以适当拆分成更小的文件,更利于缓存。

不过这也要根据实际情况,不是说完全不需要合并,而是不需要像HTTP/1.1那样极端地合并。

4. 服务器推送要谨慎

服务器推送虽然能加快加载,但是如果推送的资源浏览器已经缓存了,反而会浪费带宽。所以建议只推送关键的、确定未缓存的资源,或者用Cookie等方式判断是否需要推送。

八、写在最后

HTTP/2协议入门:从理论到实战。

HTTP/2是Web协议的一次重大升级,解决了HTTP/1.1的很多痛点,能大幅提升页面加载速度,改善用户体验。而且配置很简单,Nginx只需要加一个http2参数就能开启,浏览器兼容性也很好,不支持的会自动降级。

如果你还在使用HTTP/1.1,强烈建议升级到HTTP/2。这是一个低成本、高回报的优化,不需要改代码,只需要改一下Nginx配置,就能让网站速度提升很多。

当然,HTTP/2不是银弹,不能解决所有性能问题。要让网站更快,还需要其他方面的优化,比如图片优化、代码优化、缓存优化、CDN等。但是HTTP/2是基础,在这个基础上做其他优化,效果会更好。

未来HTTP/3(基于QUIC)也在制定中,会进一步提升性能和安全性。但是现在HTTP/2已经足够好了,先用起来,等HTTP/3成熟了再升级。

希望这篇文章能帮助大家了解HTTP/2,并顺利升级到HTTP/2。如果有什么问题,欢迎在评论区交流。