什么是 HTTP Keep-Alive?一文讲清连接复用机制

HTTP Keep-Alive,也叫 HTTP 持久连接,核心作用是:让多个 HTTP 请求复用同一条 TCP 连接,避免每次请求都重新建立连接。

一、为什么需要 Keep-Alive?

一个网页通常需要请求 HTML、CSS、JavaScript、图片等许多资源。

1. 没有 Keep-Alive 时

如果不使用 Keep-Alive,每个 HTTP 请求都需要单独建立和关闭 TCP 连接:

text 复制代码
建立 TCP 连接 1
发送 GET /index.html
接收响应
关闭 TCP 连接 1

建立 TCP 连接 2
发送 GET /logo.png
接收响应
关闭 TCP 连接 2

建立 TCP 连接 3
发送 GET /background.png
接收响应
关闭 TCP 连接 3

请求三个资源,就建立三条 TCP 连接。每次都要经历 TCP 握手和连接关闭;使用 HTTPS 时,还会增加 TLS 握手开销。

2. 使用 Keep-Alive 时

使用 Keep-Alive 后,同一条 TCP 连接可以依次承载多个 HTTP 请求和响应:

text 复制代码
建立 TCP 连接

发送 GET /index.html
← 接收 index.html

发送 GET /logo.png
← 接收 logo.png

发送 GET /background.png
← 接收 background.png

一段时间没有新请求
关闭 TCP 连接

它们之间的关系是:

text 复制代码
一条 TCP 连接
├── HTTP 请求 1 + 响应 1
├── HTTP 请求 2 + 响应 2
└── HTTP 请求 3 + 响应 3

Keep-Alive 不是让某一个 HTTP 响应一直不结束,而是让底层 TCP 连接在一次响应结束后继续存活,供后续 HTTP 请求复用。

二、HTTP/1.0 和 HTTP/1.1 的区别

HTTP/1.0 默认在一次请求和响应结束后关闭 TCP 连接。如果希望复用连接,通常需要明确声明:

http 复制代码
GET /index.html HTTP/1.0
Host: example.com
Connection: keep-alive

HTTP/1.1 默认使用持久连接。即使请求中没有写 Connection: keep-alive,通常也会保留连接:

http 复制代码
GET /index.html HTTP/1.1
Host: example.com

如果客户端或服务器不希望继续复用,需要明确声明:

http 复制代码
GET /index.html HTTP/1.1
Host: example.com
Connection: close
http 复制代码
HTTP/1.1 200 OK
Connection: close

Connection 是逐跳请求头,只对当前客户端与下一跳服务器或代理之间的连接有效,不是端到端请求头。

三、一次 Keep-Alive 请求是怎样运行的?

客户端首先建立 TCP 连接,然后发送第一个请求:

http 复制代码
GET /index.html HTTP/1.1
Host: example.com

服务器返回:

http 复制代码
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 5

hello

客户端根据 Content-Length: 5 读取完 hello 后,知道这次 HTTP 响应已经结束。

此时 TCP 连接没有关闭,客户端可以在同一条连接上继续发送:

http 复制代码
GET /user HTTP/1.1
Host: example.com

服务器可以继续返回:

http 复制代码
HTTP/1.1 200 OK
Content-Length: 6

 world

整个过程如下:

如果客户端准备发送下一次请求时发现连接已经关闭,就会重新建立 TCP 连接。

四、消息边界很重要

多个请求和响应共用一条 TCP 连接时,接收方必须知道:当前消息在哪里结束,下一条消息从哪里开始?

这就是 HTTP 消息边界问题

1. 使用 Content-Length

Content-Length 用来声明响应体的总字节数

http 复制代码
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 11

hello world

即使指定了 Content-Length,Body 也不需要一次性发送完。服务端可以在同一个 HTTP 响应中分多次写入 Body

例如服务端的代码可以是:

javascript 复制代码
res.write("hello");
// 等待 1 秒
res.write(" world");
res.end();

无论服务端分几次写入,客户端累计读取满11字节后,就知道响应结束了,接下来读取的内容属于下一条 HTTP 消息

2. 使用分块传输(Transfer-Encoding: chunked)

如果服务端不能提前确定响应体总大小时,可以分块写入,并在内容结束时使用分割符

例如服务端的代码可能是:

javascript 复制代码
res.write("hello");
// 等待 1 秒
res.write(" world");
res.end();

实际的响应为

http 复制代码
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

5
hello
6
 world <- 注意这里有个空格,所以是6个字节
0
       <- 注意这里有个空行

块长度使用十六进制,0\r\n\r\n 表示响应体结束

分块响应结束后,TCP 连接不会因此自动关闭,仍然可以继续承载下一次 HTTP 请求和响应

3. 关闭 TCP 连接

某些响应既没有 Content-Length,也没有分块编码,客户端只能通过 TCP 连接关闭判断响应体结束:

text 复制代码
读取响应体 → 收到 TCP FIN → 响应结束

这种方式关闭了底层连接,所以无法继续复用。

4. 协议规定没有响应体

部分响应不包含消息体,因此读完响应头就结束,例如:

  • HEAD 请求的响应
  • 204 No Content
  • 304 Not Modified
  • 部分 1xx 响应

五、Keep-Alive 不会永久保持连接

HTTP 持久连接通常会受到以下限制:

  • 空闲超时:一段时间没有新请求,服务器或代理就关闭连接
  • 最大请求数:一条连接处理一定数量的请求后关闭
  • 服务端负载:服务器资源紧张时可能主动回收空闲连接
  • 中间网络设备:反向代理、负载均衡器或防火墙可能提前关闭连接

服务器可能返回类似的提示:

http 复制代码
Connection: keep-alive
Keep-Alive: timeout=5, max=100

大致表示连接空闲 5 秒后可能被关闭,并且最多处理 100 个请求。不过这些值通常只是提示,实际行为取决于服务器和中间代理的配置

服务器如果决定处理完当前响应后关闭连接,可以返回:

http 复制代码
Connection: close

客户端读取完本次响应后,不应再通过该连接发送新请求

六、HTTP/1.1 Keep-Alive 的局限

HTTP/1.1 可以复用 TCP 连接,但通常仍然按照下面的顺序通信:

text 复制代码
请求 1 → 响应 1 → 请求 2 → 响应 2

HTTP/1.1 还设计过管线化,可以连续发送多个请求:

text 复制代码
请求 1
请求 2
请求 3
响应 1
响应 2
响应 3

但服务器必须按照请求顺序返回响应。如果响应 1 很慢,响应 2 和响应 3 即使已经准备好,也不能越过响应 1,这叫作应用层的队头阻塞。

因此,浏览器通常不会使用 HTTP/1.1 管线化,而是会为同一个域名建立多条 TCP 连接。

HTTP/2 支持在一条连接上并发传输多个请求和响应:

text 复制代码
一条 TCP 连接
├── Stream 1:请求/响应 A
├── Stream 3:请求/响应 B
└── Stream 5:请求/响应 C

这叫多路复用。不同请求和响应的数据帧可以交错传输,不再要求完成一个响应后才能传输下一个响应。

七、总结

HTTP Keep-Alive 允许多个 HTTP 请求和响应复用同一条 TCP 连接。一次响应结束后,连接不会立即关闭,而是继续等待后续请求,直到客户端、服务器或中间代理将其关闭。

连接复用的前提是每条 HTTP 消息都有明确的边界。边界通常由 Content-Length、Transfer-Encoding: chunked、协议规定的无响应体语义或连接关闭来确定。


✨ 微信公众号【凉凉的知识库】同步更新,欢迎关注获取最新最有用的知识 ✨

相关推荐
wlsh151 小时前
HTTP 协议
http
清泓y2 小时前
UE基础知识与引擎架构面试题
面试·架构·ue5·ue4·游戏程序
触底反弹2 小时前
💡 React 父子组件通信:一个进度条教会我的 5 件事
前端·react.js·面试
白狐_7982 小时前
【408计算机网络|第01章|408-CN-01】计算机网络概述与体系结构:性能指标、分层、OSI与TCP/IP
网络协议·tcp/ip·计算机网络
MrDJun2 小时前
长期稳定跑网页监控:TLS 指纹、代理选路与请求节流的工程实践
运维·爬虫·python·网络协议·网站监控
白狐_7983 小时前
【408计算机网络|第03章·上|408-CN-03A】数据链路层(上):组帧、差错控制与可靠传输
网络·网络协议·计算机网络
老赵的博客3 小时前
工控机之udp远程控制
网络·网络协议·udp
怪奇云呼军3 小时前
闪电智能 Voice Agent 怎样根据语速、停顿和追问方式切换话术?策略引擎拆解
开发语言·人工智能·网络协议·算法·语音识别·web app
努力努力再努力wz3 小时前
【分布式系统与 RPC 框架系列】从单机瓶颈到远程调用:一文理解分布式架构与 RPC 原理
linux·网络·c++·分布式·网络协议·rpc·架构