- ldleStateHandler 可以实现心跳功能,当服务器和客户端没有任何读写交互时,并超过了给定的时间,则会触发用户 handler 的 userEventTriggered 方法。用户可以在这个方法中尝试向对方发送信息,如果发送失败,则关闭连接。
- IdleStateHandler 的实现基于 EventLoop 的定时任务,每次读写都会记录一个值,在定时任务运行的时候。通过计算当前时间和设置时间和上次事件发生时间的结果,来判断是否空闲。
- 内部有 3 个定时任务,分别对应读事件,写事件,读写事件。通常用户监听读写事件就足够了。
- 同时,IdleStateHandler 内部也考虑了一些极端情况:客户端接收缓慢,一次接收数据的速度超过了设置的空闲时间。Netty 通过构造方法中的 observeOutput 属性来决定是否对出站缓冲区的情况进行判断。
- 如果出站缓慢,Netty 不认为这是空闲,也就不触发空闲事件。但第一次无论如何也是要触发的。因为第次无法判断是出站缓慢还是空闲。当然,出站缓慢的话,可能造成 OOM,OOM 比空闲的问题更大。
- 所以,当你的应用出现了内存溢出,0OM之类,并且写空闲极少发生(使用了 observeOutput 为 tnue)那么就需要注意是不是数据出站速度过慢。
- 还有一个注意的地方:就是 ReadTimeoutHandler ,它继承自 ldleStateHandler,当触发读空闲事件的时候,就触发 ctx.fireExceptionCaught 方法,并传入一个 ReadTimeoutException,然后关闭 Socket。
- 而 WriteTimeoutHandler 的实现不是基于 IdleStateHandler 的,他的原理是,当调用 write 方法的时候,会创建一个定时任务,任务内容是根据传入的 promise 的完成情况来判断是否超出了写的时间。当定时任务根据指定时间开始运行,发现 promise 的 isDone 方法返回 flse,表明还没有写完,说明超时了,则抛出异常。当 write方法完成后,会打断定时任务。