[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ]
📢 大家好,我是 WeiyiGeek,一名深耕安全运维开发(SecOpsDev)领域的技术从业者,致力于探索DevOps与安全的融合(DevSecOps),自动化运维工具开发与实践,企业网络安全防护,欢迎各位道友一起学习交流、一起进步 🚀,若此文对你有帮助,一定记得点个关注⭐与小红星❤️或加入到作者知识星球『 全栈工程师修炼指南』,转发收藏学习不迷路 😋 。
Nginx 中 http2 协议介绍与服务搭建资源推送
描述:前面《Nginx | HTTP 反向代理:gRPC 高性能远程过程调用(RPC)框架》文章中,我们介绍了 Google 推出的 gRPC 服务框架,并在 Nginx 反向代理 gPRC 服务时它也是基于 HTTP/2 实现的,HTTP2.0 协议相对于 HTP1.1 协议有很大的一个性能提升。另外,作者前面的 Nginx 演示配置中都开启了 HTTP/2 支持,但是并未对其详细介绍,和对性能到底有那些提升,以及演示其资源推送功能,所以接下来我们一一详细介绍与实践。
温馨提示:若文章代码块中存在乱码或不能复制,请联系作者,也可通过文末的阅读原文链接,加入知识星球中阅读,原文链接:https://articles.zsxq.com/id_fib851xw86fq.html
HTTP2 协议介绍
HTTP/2 是 HTTP 协议的第二个主要版本,于 2015 年发布,旨在解决 HTTP/1.x 的性能瓶颈,提升网页加载速度和网络效率,解决了队头阻塞(HTTP/1.x 中一个请求阻塞后续请求),高延迟(减少多次 TCP 连接和握手开销)以及头部冗余(重复的头部字段占用带宽),显著提升了 Web 性能,HTTP/2 已成为现代互联网的主流协议被广泛使用。
HTTP/2.0 协议的核心概念:
连接(Connection):单个 TCP 连接,可以承载多个双向数据流(Stream)
流(Stream):双向通讯的数据流,每个页面可能对应一个Stream,每个流可以包含多个消息
消息(Message):每个消息包含1个或多个帧,对应 HTTP/1.x 请求和响应
帧(Frame):最小概念单元,以二进制压缩格式存储 HTTP/1.x 内容,包括 Headers 和 Data
此文,我们再详细的介绍一下 Frame 帧的格式,如下图所示:包含长度、类型、标识,消息号(4字节32位)以及数据内容等。
HTTP/2 主要特性与改进:
[x] 二进制传输(核心): 将文本格式(HTTP/1.x)改为二进制格式,解析更快、更高效,且减少错误。
[x] 头部压缩(核心): 使用 HPACK 算法压缩请求头,减少冗余数据(如 Cookie、User-Agent),降低带宽消耗,例如:相似请求间仅传输变化部分,大幅度减少重复头部信息的传输,算法主要包含三个部分:
静态字典:将常用的 header 字段整成字典,比如
{"method":"GET"}就可以用单个数字 2 来表示。动态字典:没有在静态字典里面的一些头部字段,则用动态字典。
Huffman 编码:压缩编码。
[x] 多路复用(核心): 允许在单个 TCP 连接上并行传输多个请求和响应,即传输中无序,接收时组装(利用缓存),解决了 HTTP/1.x 的队头阻塞问题,大幅提升并发效率,减少了我们的三次握手和四次握手的开关连接的一个过程,工作效率也最高。
[x] 服务器资源推送: 服务器可以主动向客户端并行推送资源(如 HTML、CSS、JS),减少额外的请求延迟,
[x] 自定义资源优先级:允许客户端为请求分配优先级,确保重要资源(如 HTML)优先传输,例如在某些场景中CSS 可能对重要,需要先给浏览器进行渲染。
[x] 更安全的默认要求:主流浏览器仅支持加密的 HTTP/2(基于 TLS/1.2+),即必须SSL全站加密,而非明文传输才能真正使用 HTTP/2。
HTTP/2.0 与 HTTP/1.x 对比如下表格所示:
| 特性 | HTTP/1.0 | HTTP/1.1 | HTTP/2 | 说明与影响 |
|---|---|---|---|---|
| 协议格式 | 文本协议 | 文本协议 | 二进制协议 | HTTP/2使用二进制帧传输,解析效率更高,错误率更低 |
| 连接管理 | 短连接(默认) | 持久连接(默认) | 单连接多路复用 | HTTP/2单个TCP连接可处理多个并行流,减少连接开销 |
| 并发请求 | 每个请求需新连接 | 多个TCP连接(6-8个/域名) | 单个连接内多路复用 | HTTP/2彻底解决队头阻塞,无需域名分片等优化技巧 |
| 头部传输 | 不压缩 | 不压缩 | HPACK头部压缩 | 减少重复头部传输(如Cookie、User-Agent),节省带宽40-90% |
| 数据压缩 | 可选(如gzip) | 可选(如gzip) | 可选(如gzip) | 主体压缩方式不变,但HTTP/2有更好的整体压缩 |
| 服务器推送 | 不支持 | 不支持 | 支持(主动推送) | 服务器可预测客户端需求,提前推送CSS/JS等资源 |
| 请求优先级 | 无 | 无 | 流优先级控制 | 客户端可指定资源加载优先级(如HTML优先于图片) |
| 队头阻塞 | 严重 | 存在(管道化很少用) | 基本解决(应用层) | HTTP/2仍受TCP队头阻塞影响,但应用层已优化 |
| 安全要求 | 无 | 无 | 事实上的TLS要求 | 主流浏览器只支持加密的HTTP/2(h2),非加密的h2c较少用 |
| 握手开销 | 高(每次新连接) | 中等(持久连接) | 低(复用连接) | HTTP/2减少TCP和TLS握手次数,提升加载速度 |
| 协议协商 | 无 | Upgrade机制 | ALPN扩展 | 通过TLS的ALPN在握手时协商HTTP/2,无需额外往返 |
| 错误处理 | 关闭连接 | 关闭连接 | 更精细的连接控制 | 支持重置流(RST_STREAM)而不关闭整个连接 |
| 流量控制 | 基于TCP | 基于TCP | 基于流的流量控制 | 为每个流单独控制流量,更灵活的资源管理 |
| 典型延迟 | 高 | 中等 | 低 | 多路复用和头部压缩显著减少页面加载时间 |
| 头部大小限制 | 无明确规定 | 无明确规定 | 更高效处理大头部 | 使用索引表管理头部字段,避免重复传输 |
| 缓存策略 | 基础支持 | 增强(ETag等) | 同HTTP/1.1 | 缓存机制继承HTTP/1.1,无本质改变 |
另外,HTTP/2 为 HTTP/3 奠定了基础,HTTP/3 改用 QUIC 协议(基于 UDP),进一步解决 TCP 的队头阻塞和连接延迟问题。
好了,上面我们介简单绍了 HTTP/2.0 相关特性以及与 HTTP 1.x 协议的对比,下面我们将在 Nginx 中搭建一个 HTTP/2.0 服务,查看到 HTTP 2.0 的优势,并演示其资源推送功能,不过在此之前,同样先简单的介绍在 Nginx 中 HTTP/2.0 相关指令配置。
Nginx HTTP/2 模块指令
在 Nginx 中要完全支持 HTTP/2.0 相关功能,需在编译时启用--with-http_v2_module选项,以安装ngx_http_v2_module模块,其次必须开启 TLS/SSL 协议,需申请并配置SSL证书(如通过Let's Encrypt、自签证书),ngx_http_v2_module 帮助文档地址 https://nginx.org/en/docs/http/ngx_http_v2_module.html
# 构建脚本 Makefile ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --sbin-path=/usr/sbin/nginx --conf-path=/usr/local/nginx/conf/nginx.conf --pid-path=/usr/local/nginx/nginx.pid --error-log-path=/var/log/nginx/logs/error.log --http-log-path=/var/log/nginx/logs/access.log --lock-path=/var/run/nginx.lock --modules-path=/usr/local/nginx/modules --with-http_stub_status_module --with-http_realip_module --with-http_ssl_module --with-http_slice_module --with-http_v2_module --with-cc-opt=-O2 --with-compat # 编译安装 make -j$(nproc) && make install指令模块
http2指令用于启用 HTTP/2.0 支持,默认情况下是关闭的。
Syntax: http2 on | off; Default: http2 off; Context: http, server This directive appeared in version 1.25.1. # 基础示例 server { listen 443 ssl; # 开启 TLS/SSL 协议,启用 HTTPS 服务。 http2 on; # 启用 HTTP/2.0 支持。 ssl_certificate server.crt; # 指定 SSL 证书文件路径。 ssl_certificate_key server.key; # 指定 SSL 私钥文件路径。 }资源推送指令,用于配置服务器主动向客户端推送资源。
http2_push 指令用于将请求与对原始请求的响应一起沿着发送(推送)到指定的 uri,使用相对路径也可使用变量,并且可在同一配置级别上指定多个 http2_push 指令,但自版本1.25.1起已过时,建议在头部字段中添加Link预加载提示。
Syntax: http2_push uri | off; Default: http2_push off; Context: http, server, location # 示例 http2_push /static/css/main.css;http2_push_preload指令用于启用或禁用预加载推送,默认情况下是关闭的,启用后需在头部字段中添加Link预加载提示,以便浏览器知道哪些资源将被推送,同样自版本 1.25.1 起已过时。
Syntax: http2_push_preload on | off; Default: http2_push_preload off; Context: http, server, location # 示例:若响应头含 Link: </star.css>; rel=preload,则star.css被推送。 http2_push_preload on;请求接并发与流控制指令,用于配置 HTTP/2.0 连接并发和流控制相关参数。
http2_max_concurrent_pushes指令用于限制连接中并发推送请求的最大数量,自版本1.25.1起已过时。
Syntax: http2_max_concurrent_pushes number; Default: http2_max_concurrent_pushes 10; Context: http, serverhttp2_max_concurrent_streams指令用于设置连接中并发HTTP/2流的最大数量,自版本1.25.1起已过时。
Syntax: http2_max_concurrent_pushes number; Default: http2_max_concurrent_pushes 10; Context: http, serverhttp2_max_requests指令用于设置一个HTTP/2连接可以处理的最大请求数(包括推送请求),超过此数量后,下一个客户端请求将导致连接关闭并需要建立新的连接,自版本1.25.1起已过时,建议使用keepalive_requests指令代替。
Syntax: http2_max_requests number; Default: http2_max_requests 1000; Context: http, serverhttp2_chunk_size指令用于设置响应正文切片的最大块大小, 过低的值会导致更高的开销, 过高的值会由于HOL阻塞而损害优先级。
Syntax: http2_chunk_size size; Default: http2_chunk_size 8k; Context: http, server, location缓冲区大小设置指令,用于配置 HTTP/2.0 连接缓冲区大小相关参数。
http2_body_preread_size指令用于设置每个请求主体的缓冲区大小,默认情况下是 16k。
Syntax: http2_body_preread_size size; Default: http2_body_preread_size 64k; Context: http, serverhttp2_max_field_size指令用于限制经过HPACK压缩的请求标头字段的最大大小,默认情况下是 4k。自版本1.19.7起已过时,建议使用large_client_header_buffers指令。
Syntax: http2_max_field_size size; Default: http2_max_field_size 4k; Context: http, serverhttp2_max_header_size指令用于限制HPACK解压缩后整个请求标头列表的最大大小。对于大多数请求,默认限制应该足够了,自版本1.19.7起已过时,建议使用large_client_header_buffers指令。
Syntax: http2_max_header_size size; Default: http2_max_header_size 16k; Context: http, serverhttp2_recv_buffer_size指令用于设置每个工作进程输入缓冲区的大小。
Syntax: http2_recv_buffer_size size; Default: http2_recv_buffer_size 256k; Context: http超时控制指令,用于配置 HTTP/2.0 连接超时相关参数。
http2_idle_timeout指令用于空闲多少时间后关闭连接,自版本1.19.7起已过时,建议使用keepalive_timeout指令代替。
Syntax: http2_idle_timeout time; Default: http2_idle_timeout 3m; Context: http, serverhttp2_recv_timeout指令用于设置接收超时时间,自版本1.19.7起已过时,应该使用client_header_timeout指令。
Syntax: http2_recv_timeout time; Default: http2_recv_timeout 30s; Context: http, server另外,该模块还提供了一个内置变量$http2,可用于检测当前连接是否为 HTTP/2.0 连接,其变量标识符值为:
“h2” for HTTP/2 over TLS,
“h2c” for HTTP/2 over cleartext TCP, or an empty string otherwise.
实践演示
步骤 01.作者准备一些静态资源文件和自签证书【参考文章:Nginx | 核心知识150讲之SSL证书签发与HTTPS加密传输学习实践笔记】,以演示其 HTTP/2.0 资源推送功能。
$ cd /usr/local/nginx/html $ tree . . ├── video.html ├── img │ └── bg.png ├── video │ └── 202403192224.mp4 ├── css │ └── style.css ├── js │ └── index.js └── index.html <!-- 其中 index.html 首页,内容如下 --> tee index.html <<'EOF' <HTML> <HEAD> <meta charset="UTF-8"> <title>测试HTTP2.0推送</title> </HEAD> <BODY> <h1>测试HTTP2.0推送</h2> <BODY> </HTML> EOF <!-- 其中创建一个视频播放页面,如下所示: --> tee video.html <<'EOF' <video id="myVideo" class="responsive-video" src="/videos/202403192224.mp4" poster="/img/bg.jpg" preload="metadata" controls playsinline muted loop width="1280" height="720" crossorigin="anonymous">步骤 02.配置 Nginx 启用 HTTP/2.0 支持,并开启资源推送功能,修改完毕后验证配置并重启 Nginx 服务。tee /usr/local/nginx/conf.d/server.conf <<'EOF' # 只在连接为 HTTP/2 且支持推送时执行推送 map $http2$push_allowed { default ""; "h2" "1"; } server { # 监听 443 端口,启用 TLS/SSL 协议 listen 443 ssl; # 虚拟主机服务器名称 server_name server.weiyigeek.top; default_type text/html; # 启用 HTTP/2 支持 http2 on; # 日志文件 access_log /var/log/nginx/server.log main; error_log /var/log/nginx/server.err.log debug; # SSL 证书文件 ssl_certificate /usr/local/nginx/certs/server.crt; # ssl_certificate_key /usr/local/nginx/certs/server.key; # 加密的 SSL 证书密钥文件(根据需求选择) ssl_certificate_key /usr/local/nginx/certs/server_encrypted.key; ssl_password_file /usr/local/nginx/certs/ssl_password.txt; # 支持的 SSL/TLS 协议版本 ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; # 支持的 SSL/TLS 加密套件 ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE:ECDH:AES:HIGH:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:!NULL:!aNULL:!eNULL:!EXPORT:!PSK:!ADH:!DH:!DES:!MD5:!RC4; # SSL 会话缓存 ssl_session_cache shared:SSL:10m; # SSL 会话超时时间 ssl_session_timeout 10m; # 优先使用服务器端支持的加密套件 ssl_prefer_server_ciphers on; # 强制使用 HTTPS 访问 add_header Strict-Transport-Security "max-age=31536000;includeSubDomains;preload" always; # 根目录设置 root /usr/local/nginx/html; # 缺省文件索引页设置,即访问根目录时默认打开的文件名 index index.html; # 使用 Link 指定推送多个资源 location / { # 推送 css 和 js 文件作为预加载资源 add_header Link "</css/style.css>; as=style; rel=preload, </js/index.js>; as=script; rel=preload" always; # 缓存控制 expires 1h; add_header Cache-Control "public, no-cache"; } # 仅当连接为 HTTP/2 且支持推送时才执行推送 location = /video.html { if ($push_allowed) { # 推送 MP4 视频文件 add_header Link "</css/style.css>; as=style; rel=preload, </videos/202403192224.mp4>; as=video; type=video/mp4; rel=preload" always; # 可选:推送视频封面图 add_header Link "</img/bg.png>; as=image; rel=preload" always; # 缓存控制 expires 1h; add_header Cache-Control "public, no-cache"; } } # 特别注意:使用 http2_push、http2_push_preload 指令推送资源已失效,Nginx 1.25.1 及以后已不支持这种方式。 location /old { http2_push /css/style.css; http2_push /res/202403192224.mp4; } } EOF # 验证重载 nginx -t && nginx -s reload nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful nginx: [warn] the "http2_push" directive is obsolete, ignored in /usr/local/nginx/conf.d/server.conf:77 nginx: [warn] the "http2_push" directive is obsolete, ignored in /usr/local/nginx/conf.d/server.conf:78
温馨提示:Nginx 1.25.1 及以后版本已废弃 http2_push、http2_push_preload 等指令,不再支持资源推送功能,在配置文件中使用这些指令将会被忽略,一定要使用 add_header Link 方式来实现资源推送。
步骤 03.为了防止各位看友旧版本的 curl 工具不支持 HTTP/2.0 协议,所以这里我们使用nghttp命令行工具来测试 Nginx HTTP/2.0 协议,可通过 Github 或者通过包管理器安装,官网地址:https://nghttp2.org/
# 方式1.通过 Github 下载版本进行编译安装 # Ubuntu/Debian sudo apt-get install g++ make binutils autoconf automake \ autotools-dev libtool pkg-config zlib1g-dev libcunit1-dev \ libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev \ libc-ares-dev libjemalloc-dev libsystemd-dev cython python3-dev # CentOS/RHEL sudo yum install gcc gcc-c++ make cmake automake autoconf libtool \ pkgconfig zlib-devel openssl-devel libxml2-devel libev-devel \ jansson-devel c-ares-devel python3-devel python3-pip # 下载源码 wget https://github.com/nghttp2/nghttp2/releases/download/v1.68.0/nghttp2-1.68.0.tar.xz # 解压 xz -k -d nghttp2-1.68.0.tar.xz tar -xvf nghttp2-1.68.0.tar # 构建 ./configure --enable-app # 编译 make -j$(nproc) # 检查产物 ls src/.libs/ # 有时临时文件在这里 deflatehd h2load inflatehd nghttp nghttpd nghttpx # 主要工具包括: # nghttp - HTTP/2 客户端 # nghttpd - HTTP/2 服务器 # h2load - 负载测试工具 # nghttpx - 代理服务器 # 安装 sudo make install # 更新动态链接库缓存 sudo ldconfig /usr/local/lib # 方式2.通过包管理器安装(版本可能过旧) # redhat 系 yum install nghttp2 # debian 系 apt install nghttp2
weiyigeek.top-nghttp2测速工具图步骤 04.使用 nghttp 命令行工具测试 Nginx HTTP/2.0 支持情况,
# 访问主页路径 /usr/local/bin/nghttp -ans https://nghttp2.org ***** Statistics ***** Request timing: responseEnd: the time when last byte of response was received relative to connectEnd requestStart: the time just before first byte of request was sent relative to connectEnd. If '*' is shown, this was pushed by server. process: responseEnd - requestStart code: HTTP status code size: number of bytes received as response body without inflation. URI: request URI see http://www.w3.org/TR/resource-timing/#processing-model sorted by 'complete' id responseEnd requestStart process code size request path 1 +731.81ms +73us 731.74ms 200 6K / 3 +1.27s +732.00ms 537.07ms 200 6K /javascripts/modernizr-2.0.js 5 +1.34s +732.01ms 612.92ms 200 8K /javascripts/octopress.js 2 +1.34s * +246.02ms 1.10s 200 38K /stylesheets/screen.css # 访问 / 路径 /usr/local/bin/nghttp -anv --no-verify https://server.weiyigeek.top/ # 访问 /video.html 路径 /usr/local/bin/nghttp -anv --no-verify https://server.weiyigeek.top/video.html
![]()
weiyigeek.top-使用 nghttp 命令行工具验证图 但经过作者测试,在访问验证 HTTP/2.0 自动推送时,建议通过主流的浏览器(Firefox、Google、Edge)进行访问 /video.html 路径时,可以更加直观的看到资源推送的效果。
![]()
weiyigeek.top-使用主流浏览器验证HTTP2.0推送图 温馨提示: 若 curl 版本够新支持--http2参数也是可以进行检查 ALPN 协商,例如:
$ curl -V curl 8.4.0 # 查看详细的 HTTP/2 信息 curl -i --http2 https://server.weiyigeek.top/video.html -k HTTP/2 200 server: nginx/1.29.0 date: Sat, 10 Jan 2026 15:20:55 GMT content-type: text/html content-length: 931 last-modified: Sat, 10 Jan 2026 04:51:37 GMT etag: "6961dad9-3a3" expires: Sat, 10 Jan 2026 16:20:55 GMT cache-control: max-age=3600 link: </css/style.css>; as=style; rel=preload, </videos/202403192224.mp4>; as=video; type=video/mp4; rel=preload link: </img/bg.png>; as=image; rel=preload cache-control: public, no-cache accept-ranges: bytes
步骤 05.查看 Nginx 访问日志,可以看到资源推送的效果,由下图可知即使 index.html 中未引入 css / js 文件也将主动推送,另外在 video.html 文件中未引入 css 以及 png 文件也是一并推送的。
![]()
weiyigeek.top-利用Nginx 访问日志查看HTTP2.0消息推送图 至此,本文详细介绍了 HTTP/2.0 协议,和 Nginx 中 ngx_http_v2_module 模块指令参数,以及如何开启 HTTP/2.0 支持,并演示了其资源推送功能。
![]()
END
加入:作者【全栈工程师修炼指南】知识星球
『 全栈工程师修炼指南』星球,主要涉及全栈工程师(Full Stack Development)实践文章,持续更新包括但不限于企业SecDevOps和网络安全等保合规、安全渗透测试、编程开发、云原生(Cloud Native)、物联网工业控制(IOT)、人工智能Ai,从业书籍笔记,人生职场认识等方面资料或文章。
Q: 加入作者【全栈工程师修炼指南】星球后有啥好处?
✅ 将获得作者最新工作学习实践文章以及网盘资源。
✅ 将获得作者珍藏多年的全栈学习笔记(需连续两年及以上老星球友,也可单次购买)
✅ 将获得作者专门答疑学习交流群,解决在工作学习中的问题。
✅ 将获得作者远程支持(在作者能力范围内且合规)。
![]()
获取:作者工作学习全栈笔记
作者整理了10年的工作学习笔记(涉及网络、安全、运维、开发),需要学习实践笔记的看友,可添加作者微信或者回复【工作学习实践笔记】,当前价格¥299,除了获得从业笔记的同时还可进行问题答疑以及每月远程技术支持,希望大家多多支持,收获定大于付出!
![]()
知识推荐往期文章
🔥【最新】免费领5年企业查询VIP,效果对标天眼查会员
🔥【最新】5大互联网慈善机构,各种白嫖,你用过几个
🔥【最新】Nginx | slice 模块,实现上游大文件“化整为零”缓存
🔥【最新】中国移动所有省份套餐,都在这官方公示页面
💡【相关】Nginx | 核心知识150讲,百万并发下性能优化之其它HTTP框架下反向代理场景
💡【相关】Nginx | 核心知识150讲,百万并发下性能优化之前端静态缓存、后端动态缓存实践笔记
💡【相关】Nginx | 核心知识150讲,百万并发下性能优化之SSL证书签发与HTTPS加密传输实践笔记
💡【相关】Nginx | open_file_cache 功能,实现解决频繁 open/close 的性能顽疾
若文章对你有帮助,请将它转发给更多的看友,若有疑问的小伙伴,可在评论区留言你想法哟 💬!
![]()