第 10 / 20 篇

第 9 章 空闲检测、心跳与超时

9.1 IdleStateHandler 不会自动发送心跳

IdleStateHandler 按读、写或读写活动检测空闲,并向后传播 IdleStateEvent。它本身不会替你规定 PING/PONG 协议,也不会自动完成鉴权或判定业务健康。[6]

例如:

pipeline.addLast(new IdleStateHandler(30, 0, 0));

这个构造形式的时间单位为秒,表示一段时间未读到数据时触发读空闲事件。若它放在解码器前,读活动主要体现网络字节到达;放在某些解码器后,观察到的可能是解码后的消息活动。应根据目标定义它的位置。

9.2 先定义协议,再写处理器

可以约定客户端每隔一定时间发送 PING\n,服务端回答 PONG\n。客户端如果连续超时未得到响应,关闭连接并进入重连流程。服务端若长时间无入站数据,也可关闭空闲连接。

注意:本书默认的 ReplyHandler 尚未实现 PING/PONG,它会把 PING 当作普通文本回复。实现心跳需要增加对应分支,并写测试。

当处理空闲事件时,可以在 userEventTriggered 中检查 evt 是否是 IdleStateEvent。若不是本处理器负责的事件,应调用 ctx.fireUserEventTriggered(evt) 继续传播。

9.3 三类时间不要混用

连接超时控制“建立连接等多久”;读空闲控制“一段时间没有读到活动”;请求超时控制“某个请求等应答多久”。它们解决的不是同一个问题。

一个连接可能一直有心跳,却有某个业务请求永远没有完成。因此请求超时需要按请求 ID 单独管理,并在完成或失败后清除定时任务和待处理表。

小练习: 每秒都收到心跳,是否可以取消所有业务请求超时?