一文读懂:公有云 NLB 如何撑起百万级 TCP/UDP 长连接网关

长连接网关是实时推送、游戏、物联网等场景的核心组件。当客户端需要频繁发起请求或保持持续通信时,传统短连接会带来严重的系统开销。本文从零开始解释长连接为什么需要专门的负载均衡器,并一步步拆解公有云 NLB 的工作原理、关键优化参数以及部署注意事项,帮助你理解高并发网关背后的设计逻辑。

一文读懂:公有云 NLB 如何撑起百万级 TCP/UDP 长连接网关
封面图:ZuCDN · ZuCDN 原创

为什么你的应用需要长连接网关?与NLB TCP

我的处理经验

如果你正在处理NLB TCP,先别急着照搬网上的参数。很多业务场景下,客户端和服务端之间需要保持一条长时间的通信通道,而不是每次请求都新建、销毁连接。典型的例子包括:

  • 消息推送(如即时通讯、股票行情)—— 服务端需要主动推送数据给客户端;
  • 游戏对战(尤其实时竞技类)—— 玩家操作和状态同步要求低延迟、高频率;
  • 物联网设备上报—— 设备长期在线,定期上传传感器数据或者接收指令。

对于这些场景,如果使用 HTTP 短连接,每次建立连接(TCP 三次握手、可能还有 TLS 握手)会消耗额外的 2~3 个 RTT,同时服务端需要频繁创建与销毁 socket 文件描述符,CPU 和内存开销都很大。当并发量上升到万级、十万级,操作系统内核甚至会出现 TIME_WAIT 堆积,端口耗尽,最终导致拒绝新连接。

解决思路就是让连接“复用”——客户端和服务端建立一次连接后,双方不断发送心跳包保活,数据随意在上面传输,这就是长连接。而网关作为流量的集中入口,必须能够高效地承载和管理这些长连接。

传统常用方案的问题

配置前的检查

早期很多团队用 Nginx 或 HAProxy 做四层代理,配合 keepalived 实现高可用。但对于公有云环境,自行维护这些组件会遇到几个痛点:

  • 单点瓶颈—— 软件负载均衡器本身受限于虚拟机配置,单机处理能力有限;
  • 运维复杂—— 需要手动配置防火墙、ACL、健康检查脚本,升级内核参数;
  • 弹性差—— 流量突增时无法快速横向扩展,通常需要预先留出大量冗余资源。

公有云厂商推出的网络负载均衡(Network Load Balancer,NLB)正是为了解决这些问题而设计的。它工作在 OSI 第四层(传输层),能够原生处理 TCP 和 UDP 流量,对长连接场景有原生优势。

NLB 是什么?和 ALB/CLB 有何不同?

实际操作要点

很多人会把 NLB 和 ALB(应用负载均衡)或 CLB(传统负载均衡)混淆。简单说:

  • ALB(应用型)—— 工作在第七层,可以理解 HTTP/HTTPS 协议头,支持基于域名、路径、Cookie 的转发。但它对 TCP/UDP 长连接并不友好,因为它会中断客户端连接,再建立一条到后端的新连接,导致源 IP 被隐藏,连接状态也被终止。
  • CLB(传统型)—— 通常也支持四层转发,但实现上多基于代理模式,和后端之间是“两次连接”,仍然存在中间状态。
  • NLB(网络型)—— 走的是直接路由(DSR)或者全透明代理架构。它不修改 IP 报文,只根据五元组(源 IP、源端口、目的 IP、目的端口、协议)做哈希分发。客户端发送的 TCP SYN 到达 NLB 后,NLB 直接转发给后端服务器,后端服务器直接回复客户端,整个过程就是一次连接,客户端看到的源 IP 就是 NLB 的 VIP,后端服务器能看到真实的客户端 IP(如果开启 TOA 等选项)。

正是因为 NLB 不做协议解析、不修改报文、不建立中间连接,它的性能瓶颈极低,一台 NLB 实例可以轻松支撑数百万并发连接,延迟也只有微秒级。

NLB 优化长连接网关的关键参数

虽然 NLB 本身很强,但如果后端服务器或者客户端配置不当,依然会耗尽资源。以下是生产环境中需要重点关注的几个方面:

1. 会话保持(Session Persistence)与连接一致性

对于长连接场景,一个客户端从连接到断开都希望落在同一台后端服务器上(状态信息可能存本地内存,比如游戏房间)。NLB 默认基于五元组哈希,只要客户端 IP、端口不变(保活期间通常不变),同一连接永远会打到同一台服务器。但要注意如果客户端经过 NAT,源 IP 会变化,需要配置 NLB 的源 IP 会话保持功能(一般基于源 IP 哈希,超时时间建议设置大于心跳间隔)。

2. 健康检查的细粒度调优

NLB 的健康检查可能使用 ICMP、TCP 或 UDP 探测。对于长连接网关,建议使用TCP 三次握手探测(connect 端口),而不是只 ping。因为端口监听正常不代表业务进程正常。健康检查间隔不宜过短(默认 5 秒通常足够),否则频繁探测本身也会消耗连接资源。如果后端进程启动较慢(比如 Java 应用),需要调大健康检查超时时间不健康阈值,避免 NLB 误判。

3. 连接超时与闲置断开

NLB 本身会跟踪四层连接的状态。对于 TCP 长连接,如果客户端长时间不发数据,NLB 默认会在 60~300 秒(各云产商不同)后主动断开连接(发送 RST)。如果业务心跳间隔比这个值大,客户端连接就会被误杀。此时需要在 NLB 配置中调大空闲连接超时时间,或者确保客户端心跳间隔小于该超时时间。

4. 后端服务器的内核参数

后端服务器需要承受百万级长连接,必须调整内核参数:

  • net.ipv4.tcp_keepalive_time:减小到 120 秒左右,让内核在应用层心跳失效时快速回收僵尸连接。
  • net.ipv4.tcp_tw_reusetcp_tw_recycle:开启 reuse,不开启 recycle(NAT 环境有风险)。
  • net.core.somaxconn:放大到 65535,提升 accept 队列长度。
  • net.ipv4.ip_local_port_range:扩大客户端可用端口范围,如 10240 65535

5. MTU 与 MSS 钳制

长连接经常传输小数据包,如果网络路径中有较小 MTU(如 VPN 或隧道),容易导致分片或丢包。NLB 通常支持 MSS 钳制,可以将 TCP 报文最大分段大小强制设为 1460 或更小,避免 IP 分片。

部署架构实践:从 0 搭建一个高并发长连接网关

我的处理经验

假设你的业务是物联网设备接入,设备每次上报只需几百字节,但需要保持长连接随时接受指令。以下是在某公有云上的典型步骤:

  1. 创建 NLB 实例:选择地域,实例规格选“小型”即可(云厂商一般按每秒新建连接数、并发数等指标定价),并开启“IP 类型转发”(支持客户端直接看到源 IP)。
  2. 配置监听器:协议选 TCP,端口 8080(自定义)。关闭“保持客户端源 IP”的兼容模式(否则可能影响性能)。
  3. 添加后端服务器组:选择多台 ECS(建议偶数台,避免哈希不均),设置权重。健康检查使用 TCP:8080,间隔 5 秒,超时 3 秒,健康阈值 2,不健康阈值 3。
  4. 调整后端服务器内核:登入每台 ECS,执行 sysctl -w net.ipv4.tcp_keepalive_time=120 等参数,并永久写入 /etc/sysctl.conf
  5. 测试连接:用 netcat 模拟客户端连接,观察是否在 NLB 空闲超时(比如 300 秒)后自动断开,如果断开则调大 NLB 超时。
  6. 压力测试:使用 wrktcpreplay 模拟数万连接,监控后端服务器 CPU、内存、连接数(ss -s)。

实际部署时还可以结合 Auto Scaling:监控后端服务器组的 CPU 平均利用率或连接数,当连接数超过阈值自动扩容 ECS 数量,NLB 会自动将新连接分发到新机器。

NLB TCP:常见踩坑与排查思路

故障定位思路

  • 连接总是断开:检查 NLB 空闲超时是否太小,或者客户端心跳间隔大于超时值。
  • 后端看不到真实客户端 IP:确认 NLB 是否支持并开启了 TCP Option Address (TOA),如果后端是容器环境可能不支持,需要用 proxy protocol。
  • 新连接失败:查看后端 ss -t 确认是否 socket 队列满(Recv-QSend-Q 非零),调大 net.core.somaxconn
  • UDP 长连接注意:UDP 无状态,NLB 的会话保持需要基于源 IP + 源端口哈希,如果客户端端口经常变化,会导致后端分布不均,建议使用类似 QUIC 的 connection ID 做路由。

总结

验证与回滚

公有云 NLB 是承载高并发 TCP/UDP 长连接网关的最佳起点。它硬件加速、弹性伸缩、开箱即用,免去了自建集群的运维烦恼。但长连接优化不止依赖负载均衡器本身,还需要后端服务器正确配置内核参数、合理设置心跳与超时,以及配合健康检查与弹性伸缩策略。希望本文能帮你扫清概念盲区,在实际项目中少走弯路。把这些步骤跑通后,NLB TCP基本就能稳定落地。

延伸阅读