TCP 长连接和短连接有什么区别?keepalive 是什么?
简化版
短连接:每次通信都「建连 → 传数据 → 断连」,用完即关。长连接:建一次连接后复用,多次通信不重复建连,空闲时靠心跳维持。长连接省去了频繁三次握手/四次挥手的开销,适合高频通信;但要额外维护连接和处理保活。TCP keepalive 是 TCP 自带的保活机制,注意它和 HTTP Keep-Alive 是两回事。
详细版
短连接 vs 长连接:
| 维度 | 短连接 | 长连接 |
|---|---|---|
| 建连 | 每次通信都建/断 | 建一次,复用多次 |
| 开销 | 每次都有握手/挥手开销 | 省去重复建连 |
| 资源占用 | 连接存活时间短 | 长期占用连接资源 |
| 适合 | 低频、偶发请求 | 高频通信(数据库、RPC、IM、推送) |
长连接要解决的问题:连接长期空闲时,怎么知道对方还活着?靠保活/心跳:
- TCP keepalive:TCP 协议栈自带的机制。连接空闲一段时间(Linux 默认 2 小时)后,自动发探测包,若对方无响应则判定连接失效并关闭。
- 应用层心跳:应用自己定时发心跳包(如每 30 秒),更灵活、更及时,是实际项目更常用的做法。
完整版教学
一、为什么要用长连接
建立 TCP 连接要三次握手(1 个 RTT),关闭要四次挥手,主动关闭方还要 2MSL 的 TIME_WAIT。如果每次请求都建一次连、关一次连:
- 频繁握手/挥手带来明显延迟和 CPU 开销;
- 主动关闭方堆积大量 TIME_WAIT,可能端口耗尽(详见「TIME_WAIT 和 CLOSE_WAIT」那道题)。
高频通信场景(数据库连接、微服务 RPC、即时通讯、消息推送)用长连接 + 连接池复用,把「建连成本」摊薄到多次请求上,性能好很多。这也是数据库连接池、HTTP/1.1 默认开启 Keep-Alive 的原因。
二、长连接的代价:要维护和保活
长连接不是免费的:
- 占用资源:每条连接占文件描述符和内存,长期不关会累积,服务端要控制连接数;
- 需要保活:空闲连接可能被中间设备(NAT、防火墙)悄悄断开而两端不知道,形成「半打开连接」——一方以为还连着,发数据才发现对方早没了;
- 需要处理断线重连:连接可能因网络波动断开,应用要能检测并重建。
保活机制就是为了及时发现死连接、清理资源。
三、TCP keepalive vs HTTP Keep-Alive:最易混的点
这两个名字几乎一样,但完全是两回事,务必分清:
| TCP keepalive | HTTP Keep-Alive | |
|---|---|---|
| 层次 | 传输层(TCP 协议) | 应用层(HTTP 协议) |
| 作用 | 探测连接是否还存活、清理死连接 | 复用同一个 TCP 连接发多个 HTTP 请求 |
| 触发 | 空闲超时后发探测包(默认 2 小时) | 请求头 Connection: keep-alive |
| 目的 | 保活/清理 | 避免每个 HTTP 请求都重新建 TCP 连接 |
记住:TCP keepalive 是「探活」,HTTP Keep-Alive 是「连接复用」。面试问到别混。
四、为什么应用层心跳比 TCP keepalive 更常用
TCP keepalive 有几个短板,导致实际项目常用应用层心跳代替:
- 默认间隔太长:Linux 默认 2 小时才探测一次,死连接要拖 2 小时才发现,太慢(虽然可调,但要改系统参数);
- 粒度粗:它只能探测「TCP 连接通不通」,探测不了「对方应用是不是假死」(进程卡住但 TCP 栈还在应答);
- 应用层心跳更灵活:可以自定义间隔(如 30 秒)、可以携带业务信息、还能顺便检测应用层是否正常。
所以 IM、推送、RPC 框架(Dubbo、gRPC)大多自己实现应用层心跳。
五、常见误区
- ❌ 把 TCP keepalive 和 HTTP Keep-Alive 当成一回事——一个探活(传输层),一个连接复用(应用层)。
- ❌ 以为长连接一定更好——低频/偶发请求用短连接更省资源,长连接要维护成本。
- ❌ 以为连接建立后就一直可靠——中间设备可能悄悄断开形成半打开连接,需要心跳发现。
- ❌ 依赖 TCP keepalive 及时发现死连接——默认 2 小时太慢,实际多用应用层心跳。
六、常见误区与追问
| 考点 | 正确口径 |
|---|---|
| 短连接 | 一次请求/响应后关闭,建连成本高 |
| 长连接 | 复用同一 TCP 连接,减少握手开销 |
| TCP keepalive | 内核层探测空闲连接是否仍可用 |
| 应用心跳 | 业务层更可控地判断对端存活和业务可用 |
HTTP Keep-Alive: reuse TCP connection
TCP keepalive: probe idle TCP peer
application heartbeat: ping/pong at business layer
HTTP Keep-Alive 和 TCP keepalive 名字像,但一个是连接复用,一个是空闲探活。
- 误区:长连接就是永远不断开。 长连接也会受空闲超时、负载均衡、网络中断和应用策略影响。
- 误区:TCP keepalive 可以替代所有应用心跳。 TCP keepalive 默认间隔往往很长,只能判断连接层存活,不能判断业务是否正常。
- 误区:短连接一定更安全更稳定。 短连接减少连接占用,但频繁握手会增加延迟和系统开销。
- 追问:为什么 HTTP/1.1 默认长连接? 复用 TCP 连接可以减少三次握手和慢启动成本。
- 追问:长连接的代价是什么? 服务端要维护连接状态、文件描述符、内存和超时清理策略。
- 追问:如何设计心跳? 根据业务延迟容忍度设置 ping/pong 间隔和超时次数,并考虑网络抖动避免误判。
七、加强记忆
短连接每次建/断、适合低频;长连接复用连接、省去重复握手挥手、适合高频通信,但要维护连接和保活。保活有 TCP keepalive(传输层探活,默认 2 小时太慢)和应用层心跳(更灵活常用)。切记 TCP keepalive(探活)和 HTTP Keep-Alive(连接复用)是两个不同层次的东西。