← 返回题目列表

Node.js HTTP Agent 和 keep-alive 有什么作用?

中等 第 23 / 27 题 更新于 2026/07/29
Node.jsHTTP Agentkeep-alive连接池

简化版

HTTP Agent 负责管理 Node.js 客户端请求的连接复用。开启 keep-alive 后,可以复用 TCP 连接,减少握手开销,提高吞吐;但要配置最大连接数、空闲超时和错误处理,避免连接泄漏或压垮下游。

详细版

Node.js 发起 HTTP 请求时,Agent 会管理 socket。 默认情况下连接复用策略可能不满足高并发服务需要。

import http from 'node:http'

const agent = new http.Agent({
  keepAlive: true,
  maxSockets: 100,
  maxFreeSockets: 20,
  timeout: 30_000
})

在 BFF、网关、微服务调用里,合理的 keep-alive 能显著减少 TCP/TLS 握手开销。面试要强调:连接池不是越大越好,要按下游容量和自身并发配置。

完整版教学

一、每次新建连接的成本并不低

HTTP 调用不是只有业务接口耗时。 如果每次请求都新建 TCP 连接,还要经历握手;HTTPS 还要 TLS 握手。 短请求高频调用时,连接建立成本会很明显。

无复用:
DNS -> TCP 握手 -> TLS 握手 -> 请求 -> 响应 -> 关闭

keep-alive:
首次建连 -> 多次请求复用同一连接

假设一次 TCP/TLS 建连需要 50ms,接口业务处理只要 20ms。 不复用连接时,大部分时间都花在建连上。 keep-alive 能把重复握手成本摊薄。

二、Agent 是客户端连接池管理者

Node.js 的 HTTP Agent 负责为请求分配 socket。 它会维护正在使用的连接、空闲连接和等待队列。 配置不当时,要么连接太少导致排队,要么连接太多压垮下游。

const agent = new http.Agent({
  keepAlive: true,
  maxSockets: 200,
  maxFreeSockets: 50
})
配置含义风险
keepAlive是否复用连接不开会增加握手
maxSockets每个目标最大并发连接太大会压下游
maxFreeSockets最大空闲连接数太大会占资源
timeoutsocket 超时太长会挂住

一个服务如果同时调用 5 个下游,每个下游 maxSockets 设 200,理论上可能建立 1000 条连接。 这要和机器资源、下游限流和负载均衡能力一起评估。

三、keep-alive 提升吞吐但会带来空闲连接管理

连接复用不是没有代价。 空闲 socket 会占用文件描述符和内存。 如果对端关闭了空闲连接,本端复用时可能遇到 ECONNRESET。 因此要配置空闲超时和错误重试。

连接池状态:
busy sockets -> 正在请求
free sockets -> 等待复用
closed sockets -> 被回收

如果系统 QPS 从 1000 降到 10,空闲连接还长时间保留,就会浪费资源。 合理的 free socket 上限和 timeout 能让连接池自动收缩。

四、BFF 和网关最容易从 Agent 配置获益

前端 BFF 常把一个页面请求拆成多个后端接口调用。 如果每次都新建连接,BFF 自身延迟会被放大。 连接复用能降低 P95 延迟。

页面请求
-> BFF
   -> 用户服务
   -> 商品服务
   -> 推荐服务

假设 BFF 每个页面调用 3 个服务,每个服务建连多 40ms。 没有连接复用时,串行调用可能多出 120ms。 并行调用也会增加下游连接压力。

五、连接池大小要根据下游容量配置

很多人把 maxSockets 调很大,以为吞吐就会提升。 如果下游只能稳定处理 100 并发,你给它打 1000 条连接,只会增加排队、超时和熔断。 连接池是背压的一部分。

合理配置:
自身并发
下游容量
超时时间
重试策略
连接池大小

例如下游 P95 100ms,希望每秒 500 请求,理论并发约 50。 再加一些冗余,连接池设到 100 可能够用,不必一上来 1000。

六、现代 fetch/undici 也有类似连接管理

Node.js 现代版本里的 fetch 基于 undici,也有 dispatcher、连接池等概念。 虽然 API 名称不同,但思想一样:复用连接、限制并发、管理空闲资源。 面试中可以把 Agent 作为经典入口,再说明新客户端库也要关注连接池。

记忆钩子:Agent 像打车调度站,keep-alive 让同一辆车多跑几单。

回答时别只说“提高性能”。 要说清楚减少握手、管理 socket、控制下游压力和处理空闲连接。

七、常见误区与追问

  • 误区:keep-alive 开了就一定没有问题。 还要配置连接数、空闲连接、超时和错误重试。
  • 误区:maxSockets 越大吞吐越高。 过大可能压垮下游或让本机文件描述符耗尽。
  • 误区:连接复用只影响服务端。 Node 作为 HTTP 客户端调用下游时同样需要连接池。
  • 追问:为什么 HTTPS 更需要复用? TLS 握手成本更高,复用连接能减少重复握手。
  • 追问:ECONNRESET 和 keep-alive 有什么关系? 对端可能关闭空闲连接,本端复用时会遇到连接重置,需要重试和超时处理。
  • 追问:BFF 中如何配置? 按下游服务分别配置连接池、超时和限流,不要所有服务共用一个粗暴默认值。

八、加强记忆

HTTP Agent 题抓“连接复用 + 连接池治理”。keep-alive 减少 TCP/TLS 握手,Agent 管 socket;配置要看下游容量,配合超时、重试和空闲连接回收。性能优化的另一面是别把下游打爆。