第 9 / 20 篇

第 8 章 连接生命周期与正确关闭

8.1 常见事件的意思

事件 可以先这样理解
channelRegistered Channel 注册到 EventLoop
channelActive 连接进入活动状态
channelRead / channelRead0 收到一条进入当前处理器的消息
channelReadComplete 当前一轮读事件结束,不代表业务消息结束
channelInactive 连接变为非活动状态
exceptionCaught 处理传播过来的异常

握手、鉴权等上层状态不一定与 channelActive 相同。例如 TCP 已连接,不代表 TLS 握手成功,更不代表用户已登录。

8.2 为什么先发送,再在监听器里关闭

示例对 quit 的处理为:

ctx.writeAndFlush("再见\n")
   .addListener(ChannelFutureListener.CLOSE);

它表达“这次写操作完成后关闭”。如果先调 writeAndFlush 再立即调 close,就可能过早关闭,影响待发送的数据。即使监听器触发,也不能据此证明对方业务已消费这条消息。

write 是把消息交给出站处理过程,flush 请求把待写内容推进到底层。高吞吐场景可以批量 write 后再 flush;初学示例每次直接使用 writeAndFlush,便于观察。

8.3 断线不等于立即可见

拔网线、设备休眠、对端崩溃等情况下,本地不一定马上收到明确的关闭通知。应用要按业务要求设计空闲检测、请求超时、心跳和重连。

重连不是简单死循环:应设置退避、随机抖动、最大频率与退出条件;断线时已发送但未获应答的请求处于不确定状态。若要重试修改数据的操作,需要幂等键或去重机制。

小练习: channelReadComplete 能否当作“收到一条完整订单”的判断条件?