ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

长连接服务端:考量点、观测指标、风险预防

长连接服务端:考量点、观测指标、风险预防 目录一、服务端核心考量1. 连接资源管控2. 连接生命周期管理3. 消息处理4. 网络层面5. 集群水平扩展二、必须观测的核心指标生产告警 连接相关指标 消息流量指标 线程 内存指标❤️ 心跳相关指标 系统内核指标三、风险预防 落地手段1. 解决半开连接双层心跳业务心跳 TCP keepalive2. 防连接爆炸、fd 耗尽3. 防重连风暴服务重启 / 网络故障4. Netty 层面防护防止 IO 线程阻塞5. 堆外内存溢出预防6. 消息积压防护7. 集群有状态长连接扩容8. 超时、资源释放四、常见线上故障复盘清单以智慧充电设备上报数据Netty/TCP 长连接为场景展开服务端核心问题连接爆炸、内存泄漏、线程耗尽、消息积压、半开连接、心跳失效、GC 抖动导致连接断开。一、服务端核心考量1. 连接资源管控1文件句柄每一条 TCP 连接占用一个 fdLinux 系统有ulimit‑n限制上万设备接入很容易打满句柄直接无法新建连接。 2内存占用每个连接会有缓冲区、Channel 对象、业务状态、编解码缓存10w 连接即使空闲也会占用可观堆外内存。 3线程模型Netty NIO 是 Reactor 模型要区分IO 线程池、业务线程池禁止业务逻辑阻塞 IO 线程否则全部长连接 IO 全部卡死。2. 连接生命周期管理设备异常断电、断网不会发送正常关闭报文产生半开连接服务端认为连接还活着实际设备已经离线。重连风暴服务端重启 / 网络抖动大量设备同时重连瞬间建连接打满 CPU、句柄、线程。身份绑定一个设备只允许保留一条有效长连接设备重复登录要踢掉旧连接避免重复上报数据。3. 消息处理消息乱序、粘包拆包必须前置编解码消息接收速率 业务处理速率队列积压OOM 风险上报数据失败重试要避免服务端重复消息需要做幂等。4. 网络层面NAT 网关超时设备在 4G/5G 路由器下NAT 会话有超时时间空闲太久会被网关悄无声息断开必须心跳保活。网络带宽大量设备高频上报出口带宽打满。5. 集群水平扩展长连接是有状态连接绑定在某一台实例不能像 HTTP 无请求随便负载均衡。方案一致性 hash 把设备路由到指定实例或者网关层做长连接收敛实例下线需要优雅通知客户端重连避免大量断开报错。二、必须观测的核心指标生产告警 连接相关指标当前活跃连接数active_connections峰值、当前值对比机器 fd 上限设置阈值告警比如达到最大 fd 的 70% 告警。总新建连接数connection_create_total连接断开数connection_close_total细分原因正常关闭、心跳超时、IO 异常、业务踢下线、服务端主动关闭。半开连接数无法直接采集间接看心跳超时关闭的连接数量突增文件描述符 fd 使用率/proc/$pid/fd告警阈值 70% 消息流量指标接收消息 QPS、发送消息 QPS单连接消息速率识别异常设备疯狂发包攻击消息队列积压Netty 任务队列、业务线程池队列 size队列积压是高危信号消息处理耗时p95/p99区分 IO 耗时、业务处理耗时消息丢包、解码失败计数粘包拆包异常 线程 内存指标Netty IO 线程池活跃线程数、队列任务数IO 线程是否阻塞非常关键IO 线程不能执行业务业务线程池活跃线程、队列大小、拒绝任务次数拒绝直接告警JVM 堆内存、堆外内存DirectBuffer长连接最容易堆外 OOMNetty 大量使用直接内存很多事故不是堆 OOM是堆外内存溢出。GC 指标YoungGC 频率、FullGC 次数FullGC 会造成 STW大批量长连接超时断开。❤️ 心跳相关指标心跳接收成功次数、心跳超时断开连接数平均心跳间隔判断设备网络质量 系统内核指标TCPtcp_keepalive内核统计重传次数CPU 使用率CPU 高会导致处理消息变慢连接超时工具Prometheus Grafana 埋点SkyWalking 链路追踪服务器ss -ti查看 TCP 状态。三、风险预防 落地手段1. 解决半开连接双层心跳业务心跳 TCP keepalive1应用层心跳优先设备定时上报心跳包服务端维护每个连接最后收到数据包时间戳。策略超过 N 秒没有收到任何业务 / 心跳报文服务端主动关闭 Channel。 不要只依赖操作系统 tcp‑keepalive内核 keepalive 默认超时几小时太慢业务控制更灵活。2操作系统 TCP Keepalive 作为兜底net.ipv4.tcp_keepalive_time 300 net.ipv4.tcp_keepalive_intvl 30 net.ipv4.tcp_keepalive_probes 32. 防连接爆炸、fd 耗尽1. 调高ulimit‑n根据预估最大连接设置 2. 最大连接数限制服务端设置最大可接入连接数超过直接拒绝新连接 3. 重复登录处理设备再次建立连接找到旧 Channel主动 close 旧连接保证一个设备只有一条连接。3. 防重连风暴服务重启 / 网络故障1. 客户端实现指数退避重连不要固定间隔重连失败后 1s、2s、4s、8s 最大上限 2. 服务端重启时不要瞬间所有设备涌上来客户端增加随机抖动。4. Netty 层面防护防止 IO 线程阻塞绝对禁止业务逻辑放在 Netty IO 线程执行解码之后丢到独立业务线程池设置 Netty 缓冲区上限限制单条消息最大长度防止大报文攻击配置内存泄漏检测ResourceLeakDetector限制队列长度业务线程池设置队列上限队列满执行拒绝策略不能无界队列否则 OOM。5. 堆外内存溢出预防Netty 使用池化直接内存PooledByteBufAllocator监控 Direct Buffer 内存业务使用完 ByteBuf 必须 release防止引用泄漏JVM 参数设置-XX:MaxDirectMemorySize设置堆外内存上限。6. 消息积压防护1. 限流单连接消息速率限流某设备疯狂上报直接断开连接 2. 业务队列设置最大阈值队列积压超过阈值熔断丢弃非关键消息 3. 上报数据落盘可以投递 MQ 异步削峰不要在长连接线程做 DB 操作。7. 集群有状态长连接扩容长连接实例本地保存 channel 映射设备 id → channel扩容方案一致性 hash设备固定路由到实例实例下线优雅关闭推送指令让客户端主动重连避免大量异常断开。8. 超时、资源释放空闲检测处理器 NettyIdleStateHandler是长连接标配。java// 读空闲多久没收到数据触发事件 new IdleStateHandler(READ_IDLE,0,0, TimeUnit.SECONDS)监听 IdleStateEvent读空闲超时直接关闭连接。四、常见线上故障复盘清单fd 打满无法建立新连接 → 监控 fd 使用率调高 ulimit及时关闭僵尸半开连接。堆外 OOMByteBuf 忘记 release大报文。IO 线程阻塞业务代码写在 IO 线程所有连接全部卡死。重启瞬间大量重连风暴CPU 打满。NAT 网关切断空闲连接业务无感知大量半开连接堆积。业务线程池无界队列消息积压内存暴涨。
返回列表