HTTP(HyperText Transfer Protocol,超文本传输协议)是Web的基础协议,我们每天浏览网页、使用APP,都在使用HTTP。从1991年HTTP/0.9诞生,到1999年HTTP/1.1成为标准,HTTP协议已经陪伴我们走过了二十多年。但是,随着Web的发展,网页越来越复杂,资源越来越多,HTTP/1.1的性能瓶颈越来越明显。
2015年5月,HTTP/2(RFC 7540)正式成为IETF标准,这是HTTP协议自1999年HTTP/1.1以来的第一次重大升级。HTTP/2基于Google的SPDY协议,引入了多路复用、头部压缩、服务器推送、二进制分帧等重大改进,大幅提升了Web性能。2016年,HTTP/2开始快速普及,主流浏览器(Chrome、Firefox、Safari、Edge)都已支持,主流Web服务器(Nginx、Apache、IIS)也陆续支持。
作为一个Web开发者,了解HTTP/2是非常必要的。HTTP/2不仅能提升网站性能,还会改变我们优化Web性能的思路(很多HTTP/1.1时代的优化技巧在HTTP/2时代不再需要,甚至会适得其反)。今天就来系统地讲解HTTP/2协议详解与实践,从原理到部署,帮助你理解和使用HTTP/2。
一、HTTP/1.1的问题
在了解HTTP/2之前,我们先看看HTTP/1.1有什么问题,为什么需要升级。
1. 队头阻塞(Head-of-Line Blocking)
HTTP/1.1是基于请求-响应模型的,一个连接同一时间只能处理一个请求。虽然HTTP/1.1引入了持久连接(Keep-Alive),可以在一个TCP连接上发送多个请求,但是请求必须串行处理——必须等前一个请求的响应回来,才能发送下一个请求。
这就导致了"队头阻塞"问题:如果第一个请求很慢(比如服务器处理慢、网络延迟大),那么后面的请求都必须排队等待,即使这些请求可以很快处理完。
为了解决这个问题,浏览器通常会对同一个域名建立多个TCP连接(Chrome是6个),并行发送请求。但是,建立多个TCP连接有开销(TCP握手、慢启动),而且连接数有限制,当页面有很多资源时,还是会排队。
2. 头部冗余
HTTP/1.1的头部是文本格式,每次请求都要发送完整的头部(User-Agent、Cookie、Referer、Accept等)。很多头部字段在多次请求中是相同的(比如Cookie、User-Agent),但是每次都要重复发送,浪费带宽。
特别是Cookie,很多网站的Cookie很大(几KB甚至几十KB),每次请求都要带上,非常浪费。
3. 明文传输,解析效率低
HTTP/1.1的头部和正文都是文本格式,虽然可读性好,但是解析效率低。服务器和浏览器需要逐行解析文本,效率不高。
4. 不支持服务器推送
HTTP/1.1是严格的请求-响应模型,只能客户端请求,服务器响应。服务器不能主动推送资源给客户端。
比如,浏览器请求HTML页面,服务器返回HTML。浏览器解析HTML,发现需要CSS和JS,再发起请求获取CSS和JS。这中间有一个往返延迟(RTT)。如果服务器能在返回HTML的同时,主动把CSS和JS推送给浏览器,就能节省这个往返延迟,加快页面加载。
5. 性能优化的workaround
为了解决HTTP/1.1的性能问题,开发者们发明了很多优化技巧(workaround):
- 域名分片(Domain Sharding):把资源分散到多个域名,突破浏览器同域名连接数限制,实现更多并行连接。
- 资源合并(Concatenation):把多个CSS/JS文件合并成一个,减少请求数。
- 图片精灵(CSS Sprites):把多张小图合并成一张大图,用CSS background-position显示,减少请求数。
- 内联资源(Inlining):把小图片用Base64编码内联到CSS/HTML中,把小JS内联到HTML中,减少请求数。
- 文件压缩(Gzip):压缩响应体,减少传输量。
这些优化技巧虽然有效,但是也带来了很多问题:增加了开发复杂度、缓存效率低(合并文件后一个小改动就要重新下载整个大文件)、资源浪费(内联的资源不能被缓存)。
HTTP/2的目标,就是从协议层面解决这些问题,让这些workaround不再需要。
二、HTTP/2的发展历程
1. SPDY的诞生
2009年,Google开始研发SPDY协议(发音"speedy"),目标是降低网页加载延迟。SPDY基于TCP,引入了多路复用、头部压缩、优先级、服务器推送等特性。
2012年,Google正式发布SPDY规范,Chrome浏览器开始支持。随后,Firefox、Opera等浏览器也支持SPDY。Nginx、Apache等服务器也陆续支持SPDY。
SPDY的效果非常显著:Google内部测试显示,SPDY能让网页加载速度提升27-60%。
2. HTTP/2的制定
SPDY的成功引起了IETF(互联网工程任务组)的关注。2012年,IETF成立了HTTPbis工作组,开始制定HTTP/2标准,并以SPDY为基础。
2015年5月,HTTP/2正式成为RFC标准(RFC 7540)。HTTP/2大量借鉴了SPDY的设计,但是也做了一些调整和改进。
2016年,Google宣布将在2016年逐步放弃SPDY,转向HTTP/2。主流浏览器和服务器也纷纷支持HTTP/2,HTTP/2开始快速普及。
3. HTTP/2 vs SPDY
HTTP/2基于SPDY,但是有一些区别:
- HTTP/2使用HPACK头部压缩,SPDY使用zlib压缩(HPACK更安全,避免了CRIME攻击)
- HTTP/2的优先级方案更简单
- HTTP/2移除了SPDY中的一些特性(如SPDY的控制帧)
- HTTP/2是IETF标准,SPDY是Google的私有协议
三、HTTP/2的核心特性
HTTP/2引入了很多重大改进,下面逐一详解。
1. 二进制分帧(Binary Framing)
HTTP/2在应用层和传输层之间增加了一个二进制分帧层。所有的消息(请求和响应)都被分割成更小的帧(Frame),采用二进制格式编码。
帧的类型:
- HEADERS帧:携带头部信息
- DATA帧:携带请求/响应体
- SETTINGS帧:配置连接参数
- WINDOW_UPDATE帧:流量控制
- PRIORITY帧:优先级
- RST_STREAM帧:重置流
- PUSH_PROMISE帧:服务器推送承诺
- PING帧:心跳检测
- GOAWAY帧:关闭连接
二进制分帧的好处:
- 解析效率高:二进制比文本更容易、更快解析
- 更紧凑:二进制格式比文本更节省空间
- 更灵活:可以方便地扩展新的帧类型
- 多路复用的基础:分帧使得多个请求的帧可以交错传输
注意:HTTP/2的二进制分帧只影响传输层的编码,HTTP的语义(方法、状态码、头部、URI等)保持不变。开发者不需要改变使用HTTP的方式,只是底层传输变了。
2. 多路复用(Multiplexing)
多路复用是HTTP/2最重要的特性。在HTTP/2中,一个TCP连接上可以同时有多个"流"(Stream),每个流对应一个请求-响应。不同流的帧可以交错传输,不需要等待前一个请求完成。
这就彻底解决了HTTP/1.1的队头阻塞问题。一个连接上可以并行处理多个请求,不需要建立多个TCP连接,也不需要排队等待。
多路复用的好处:
- 解决队头阻塞:请求不再排队
- 减少连接数:一个连接就能并行处理多个请求,减少TCP握手和慢启动开销
- 降低延迟:请求可以立即发送,不需要等待
- 节省资源:减少服务器的连接数和内存占用
注意:HTTP/2解决了应用层的队头阻塞,但是TCP层仍然有队头阻塞(一个TCP包丢失会导致整个连接等待重传)。这是HTTP/2基于TCP的固有问题,HTTP/3(基于QUIC/UDP)正在解决这个问题。
3. 头部压缩(HPACK)
HTTP/2使用HPACK算法压缩HTTP头部,减少头部的传输量。
HPACK的工作原理:
- 静态表:预定义了61个常见头部字段(如:method、:path、user-agent、cookie等),用索引表示,不需要重复传输完整字段名。
- 动态表:在连接过程中,新出现的头部字段会被加入动态表,后续相同的头部可以用索引引用。
- 霍夫曼编码:对头部值进行霍夫曼编码,进一步压缩。
头部压缩的好处:
- 减少重复头部的传输(如Cookie、User-Agent每次请求都相同)
- 节省带宽,加快传输速度
- 特别适合移动网络(带宽有限、延迟高)
HPACK比SPDY的zlib压缩更安全,避免了CRIME攻击(一种通过压缩长度变化推断加密内容的攻击)。
4. 服务器推送(Server Push)
HTTP/2支持服务器主动推送资源给客户端,不需要客户端请求。
工作原理:
- 客户端请求HTML页面
- 服务器返回HTML的同时,通过PUSH_PROMISE帧告诉客户端:"我要给你推送CSS和JS"
- 服务器主动把CSS和JS推送给客户端
- 客户端解析HTML时,发现需要CSS和JS,发现已经被推送了,直接使用,不需要再发起请求
服务器推送的好处:
- 减少往返延迟(RTT):客户端不需要等解析HTML后再请求CSS/JS
- 加快页面加载:关键资源可以提前到达
- 特别适合首屏关键资源(CSS、关键JS、首屏图片)
服务器推送的注意事项:
- 不要推送已经被客户端缓存的资源(浪费带宽)
- 推送关键资源即可,不要推送所有资源
- 推送的资源要和请求的页面相关
- 浏览器可以拒绝推送(通过RST_STREAM帧)
- 服务器推送的实现和配置因服务器而异
注意:服务器推送在实际应用中效果参差不齐,有时候甚至会降低性能(如推送了缓存的资源)。需要谨慎使用,做好测试。2019年Chrome甚至宣布将移除服务器推送支持,因为实际收益有限。
5. 流量控制(Flow Control)
HTTP/2支持流量控制,防止发送方发送太快,接收方处理不过来。
流量控制是基于每个流和整个连接的。接收方通过WINDOW_UPDATE帧告诉发送方自己还能接收多少数据。发送方不能超过接收方通告的窗口大小。
流量控制的好处:
- 防止接收方被淹没
- 支持不同速度的客户端
- 可以给不同的流分配不同的流量
6. 优先级(Priority)
HTTP/2支持给每个流设置优先级,告诉服务器哪些请求更重要,应该优先处理。
比如,浏览器请求HTML、CSS、JS、图片时,可以给HTML和CSS设置高优先级,给图片设置低优先级。服务器会优先处理高优先级的请求,加快关键资源的加载。
优先级可以通过PRIORITY帧设置,也可以在HEADERS帧中携带优先级信息。
优先级的好处:
- 关键资源优先加载,加快首屏渲染
- 优化用户体验(先看到重要内容)
7. 重置流(Stream Reset)
HTTP/2支持重置一个流,而不需要关闭整个连接。
在HTTP/1.1中,如果想取消一个请求,只能关闭整个TCP连接,然后重新建立连接,开销很大。而HTTP/2可以通过RST_STREAM帧重置单个流,其他流不受影响,连接继续使用。
这对于取消大文件下载、用户跳转页面等场景很有用。
8. 连接设置(SETTINGS)
HTTP/2在连接建立时,通过SETTINGS帧协商连接参数,如:
- 最大并发流数
- 初始窗口大小
- 最大帧大小
- 头部表大小
双方可以通过SETTINGS帧调整这些参数,优化连接性能。
四、HTTP/2 vs HTTP/1.1 对比
| 对比项 | HTTP/1.1 | HTTP/2 |
|---|---|---|
| 传输格式 | 文本 | 二进制 |
| 多路复用 | 不支持(串行请求) | 支持(一个连接并行多请求) |
| 队头阻塞 | 有(应用层) | 无(应用层,TCP层仍有) |
| 头部压缩 | 无(Gzip只压缩body) | HPACK头部压缩 |
| 服务器推送 | 不支持 | 支持 |
| 流量控制 | 无(TCP层) | 有(应用层+TCP层) |
| 优先级 | 无 | 支持 |
| 加密 | 可选(HTTP/HTTPS) | 主流浏览器只支持HTTPS(h2) |
| 连接数 | 多连接(同域名6个) | 单连接(多路复用) |
| 性能优化 | 需要域名分片、资源合并、图片精灵等 | 不需要这些workaround |
HTTP/2的性能提升主要来自:
- 多路复用解决队头阻塞,减少连接数和延迟
- 头部压缩减少传输量
- 服务器推送减少往返延迟
- 优先级优化关键资源加载
五、浏览器和服务器支持情况
1. 浏览器支持
2016年,主流浏览器都已支持HTTP/2:
- Chrome:40+支持HTTP/2(2015年)
- Firefox:36+支持HTTP/2(2015年)
- Safari:9+支持HTTP/2(2015年,OS X 10.11+)
- Edge:12+支持HTTP/2(2015年,Windows 10)
- IE:IE 11不支持HTTP/2(IE已经被Edge取代)
注意:主流浏览器只支持基于TLS的HTTP/2(即h2,HTTPS),不支持明文HTTP/2(h2c)。所以,要使用HTTP/2,网站必须启用HTTPS。
2. 服务器支持
2016年,主流Web服务器也陆续支持HTTP/2:
- Nginx:1.9.5+支持HTTP/2(2015年9月),1.10+稳定支持
- Apache:2.4.17+支持HTTP/2(mod_http2模块,2015年)
- IIS:Windows 10/Server 2016的IIS 10支持HTTP/2
- LiteSpeed:5.0+支持HTTP/2
- Caddy:原生支持HTTP/2,自动HTTPS
3. CDN支持
主流CDN也支持HTTP/2:
- CloudFlare:免费支持HTTP/2
- 阿里云CDN:支持HTTP/2
- 腾讯云CDN:支持HTTP/2
- 七牛云:支持HTTP/2
- 又拍云:支持HTTP/2
六、Nginx配置HTTP/2
Nginx是最流行的Web服务器之一,下面介绍如何在Nginx中配置HTTP/2。
1. 前提条件
- Nginx版本1.9.5+(推荐1.10+稳定版)
- Nginx编译时包含httpv2module模块(默认包含)
- OpenSSL版本1.0.2+(支持ALPN,HTTP/2需要ALPN协商)
- 网站已启用HTTPS(浏览器只支持HTTPS的HTTP/2)
检查Nginx是否支持HTTP/2:
nginx -V 2>&1 | grep http_v2
# 如果输出包含--with-http_v2_module,说明支持检查OpenSSL版本:
openssl version
# 需要1.0.2+,支持ALPN2. 基本配置
在Nginx的server块中,listen指令加上http2参数:
server {
# 同时支持HTTP/1.1和HTTP/2
listen 443 ssl http2;
server_name example.com;
# SSL证书配置
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# SSL协议(HTTP/2需要TLS 1.2+)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
# 根目录和首页
root /var/www/example.com;
index index.html;
# 其他配置...
}HTTP/80端口可以重定向到HTTPS:
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}3. HTTP/2相关配置
server {
listen 443 ssl http2;
server_name example.com;
# ... SSL配置 ...
# HTTP/2最大并发流数(默认128)
http2_max_concurrent_streams 128;
# HTTP/2头部表大小(默认4096)
http2_recv_buffer_size 16k;
# 服务器推送配置(Nginx 1.13.9+支持)
# 当请求/index.html时,推送/style.css和/app.js
location = /index.html {
http2_push /style.css;
http2_push /app.js;
}
# 静态资源缓存
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
}4. 验证HTTP/2是否生效
方法1:浏览器开发者工具
- Chrome/Firefox按F12打开开发者工具
- Network面板,刷新页面
- 查看Protocol列,如果显示h2,说明使用了HTTP/2
- 如果没有Protocol列,右键表头勾选Protocol
方法2:命令行测试
# 使用curl测试(需要curl 7.43+,支持--http2)
curl -I --http2 https://example.com
# 如果响应头包含HTTP/2 200,说明支持HTTP/2
# 使用openssl测试ALPN
openssl s_client -alpn h2 -connect example.com:443 -servername example.com </dev/null 2>&1 | grep ALPN
# 如果输出ALPN protocol: h2,说明支持HTTP/2方法3:在线工具
- https://tools.keycdn.com/http2-test
- https://http2.pro/
七、Apache配置HTTP/2
Apache 2.4.17+通过mod_http2模块支持HTTP/2。
1. 启用模块
# 启用http2模块
a2enmod http2
# 重启Apache
systemctl restart apache22. 配置
<VirtualHost *:443>
ServerName example.com
DocumentRoot /var/www/example.com
# 启用HTTP/2
Protocols h2 http/1.1
# SSL配置
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
# SSL协议
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
SSLHonorCipherOrder on
# 服务器推送(Apache 2.4.19+)
<Location /index.html>
H2PushResource /style.css
H2PushResource /app.js
</Location>
</VirtualHost>八、HTTP/2性能优化实践
1. HTTP/2时代不再需要的优化
HTTP/2解决了HTTP/1.1的很多问题,一些HTTP/1.1时代的优化技巧在HTTP/2时代不再需要,甚至会适得其反:
- 域名分片(Domain Sharding):HTTP/2一个连接就能多路复用,不需要多个域名。域名分片反而会建立多个TCP连接,增加开销,而且每个连接的头部压缩表是独立的,降低压缩效率。HTTP/2时代应该把资源合并到同一个域名。
- 资源合并(Concatenation):HTTP/2多路复用,多个小文件可以并行加载,不需要合并成大文件。合并大文件反而会降低缓存效率(一个小改动就要重新下载整个大文件),而且大文件的优先级不好控制。HTTP/2时代可以适当拆分资源,保持合理的文件大小。
- 图片精灵(CSS Sprites):HTTP/2多路复用,多张小图可以并行加载,不需要合并成精灵图。精灵图会降低缓存效率,而且修改麻烦。HTTP/2时代可以使用独立的小图片,或者用SVG图标、iconfont。
- 内联资源(Inlining):HTTP/2服务器推送可以替代内联,而且推送的资源可以被缓存。内联的资源不能被缓存,增加了HTML的大小。HTTP/2时代优先使用服务器推送,而不是内联。
注意:这些优化不是完全不能用,而是不再是必须的。在某些特定场景下(如极老旧的浏览器、特殊的性能需求),可能还需要。但是对于现代浏览器,优先利用HTTP/2的特性。
2. HTTP/2时代的优化重点
HTTP/2时代,性能优化的重点转向:
- 启用HTTPS:HTTP/2需要HTTPS,而且HTTPS也是趋势。使用Let's Encrypt等免费证书。
- 优化TLS:使用TLS 1.2+,启用OCSP Stapling,会话恢复,TLS False Start,减少TLS握手开销。
- 合理使用服务器推送:推送首屏关键资源(CSS、关键JS),不要推送缓存的资源,不要推送所有资源。
- 优化缓存策略:合理设置Cache-Control,利用浏览器缓存,减少重复请求。
- 图片优化:使用WebP等现代图片格式,响应式图片,懒加载,压缩图片。
- 减少重定向:重定向会增加往返延迟,尽量避免。
- 使用CDN:CDN能加速静态资源,支持HTTP/2的CDN效果更好。
- 关键渲染路径优化:优化首屏渲染,内联关键CSS(小范围),异步加载非关键JS。
- Gzip/Brotli压缩:压缩响应体,减少传输量。Brotli比Gzip压缩率更高。
3. 渐进式部署
部署HTTP/2时,可以渐进式进行:
- 先启用HTTPS(HTTP/2的前提)
- 升级服务器到支持HTTP/2的版本
- 配置HTTP/2,测试兼容性
- 逐步移除HTTP/1.1时代的优化(域名分片、资源合并等),观察性能变化
- 尝试服务器推送等新特性
- 监控性能,持续优化
注意:HTTP/2和HTTP/1.1可以共存,Nginx的listen 443 ssl http2会同时支持两种协议,浏览器会自动协商。不需要担心旧浏览器不兼容。
九、迁移注意事项
1. HTTPS是前提
主流浏览器只支持基于TLS的HTTP/2(h2),所以网站必须启用HTTPS。如果网站还没有HTTPS,需要先配置HTTPS。
- 可以使用Let's Encrypt免费证书
- 确保所有资源都使用HTTPS(避免混合内容)
- 配置301重定向,把HTTP跳转到HTTPS
2. 兼容性
- 现代浏览器都支持HTTP/2,旧浏览器(如IE 11及以下)不支持
- 服务器会自动协商,不支持HTTP/2的浏览器会使用HTTP/1.1
- 不需要为旧浏览器做特殊处理
3. 性能不一定立即提升
HTTP/2不一定能让所有网站都立即变快,特别是:
- 网站资源很少的(几个请求),HTTP/2优势不明显
- 服务器配置不当的(如TLS配置差、没有keepalive)
- 网络环境差的(高延迟、高丢包)
- 没有移除HTTP/1.1优化的(域名分片等反而会降低HTTP/2性能)
需要做好测试和监控,根据实际情况优化。
4. 服务器资源
HTTP/2的多路复用会让一个连接处理更多请求,服务器的CPU和内存占用可能会增加。需要确保服务器有足够的资源,必要时调整worker进程数和连接数。
5. 调试工具
- Chrome/Firefox开发者工具的Network面板可以查看Protocol列
- Chrome的chrome://net-internals/#http2可以查看HTTP/2连接详情
- curl --http2可以命令行测试
- 在线工具:https://tools.keycdn.com/http2-test
十、总结
HTTP/2是HTTP协议自1999年HTTP/1.1以来的第一次重大升级,基于Google的SPDY协议,2015年成为RFC标准,2016年开始快速普及。
HTTP/2的核心特性:
- 二进制分帧:二进制格式,解析效率高,是多路复用的基础
- 多路复用:一个TCP连接并行处理多个请求,解决队头阻塞,减少连接数
- 头部压缩(HPACK):压缩HTTP头部,减少重复传输,节省带宽
- 服务器推送:服务器主动推送资源,减少往返延迟
- 流量控制:防止发送方淹没接收方
- 优先级:关键资源优先加载
- 重置流:取消单个请求而不关闭连接
HTTP/2解决了HTTP/1.1的队头阻塞、头部冗余、不支持推送等问题,大幅提升了Web性能。同时,HTTP/2也改变了Web性能优化的思路:域名分片、资源合并、图片精灵、内联资源等HTTP/1.1时代的优化技巧不再需要,甚至会适得其反。
部署HTTP/2需要:
- 启用HTTPS(浏览器只支持HTTPS的HTTP/2)
- 升级服务器到支持HTTP/2的版本(Nginx 1.9.5+、Apache 2.4.17+)
- 配置HTTP/2(listen加上http2参数)
- 逐步移除HTTP/1.1时代的优化
- 合理使用服务器推送
- 做好测试和监控
HTTP/2是Web的未来,2016年已经有越来越多的网站支持HTTP/2。作为Web开发者,了解和使用HTTP/2是必要的。希望本文能帮助你理解HTTP/2,部署HTTP/2,让你的网站更快、更好。
最后,HTTP/2不是终点,HTTP/3(基于QUIC/UDP)已经在制定中,将解决TCP层的队头阻塞问题,进一步提升Web性能。技术在不断进步,我们也要不断学习,跟上时代的步伐。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录