NP-19-实现心跳检测

Netty提供了对心跳机制的天然支持,心跳可以检测远程端是否存活,或者活跃.

IdleStateHandler

构造函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public IdleStateHandler(
int readerIdleTimeSeconds,
int writerIdleTimeSeconds,
int allIdleTimeSeconds) {

this(readerIdleTimeSeconds,
writerIdleTimeSeconds,
allIdleTimeSeconds,
TimeUnit.SECONDS);
}

public IdleStateHandler(
long readerIdleTime,
long writerIdleTime,
long allIdleTime,
TimeUnit unit) {}
  • readerIdleTime: 读超时时间,即该时间内自己未收到对方发送的消息
  • writerIdleTime:写超时时间,即自己在该时间内没向对方发送消息
  • allIdleTime:读写超时时间
  • unit:时间单位

Note:

  1. 第一个构造函数调用第二个构造函数,时间单位默认为秒。
  2. 超时时间设置为0,表示disable,即不设置该项。
  3. 一般是在通信双方没有业务消息交互后,然后又超过了设置的超时时间,则需要以发送心跳信息来保持长连接,另外也能检测对方是否宕机。

Server端

一般在ChannelPipeline第一个加入以下:

1
pipeline.addLast(new IdleStateHandler(5, 0, 0));

第一个参数为5,表示在服务器端会每隔5秒来检查一下ChannelHandler的channelRead()方法被调用的情况,即是否收到客户端的消息,如果在5秒内该通道链上的所有ChannelHandler的channelRead()方法都没有被触发,就会触发调用ChannelHandler的userEventTriggered()方法。

我们可以写一个ChannelHandler,重写其userEventTriggered()方法,判断如果两次没接到心跳消息,就主动断开与客户端的连接。

Client端

一般在ChannelPipeline第一个加入以下:

1
pipeline.addLast(new IdleStateHandler(0, 4, 0));

第二个参数为4,表示客户端每隔4秒会检查一下ChannelHandler的write()方法被调用情况,即客户端4秒内是否向服务端发送过消息,如果在4秒内该通道链上的所有ChannelHandler的write()都没有被调用,就会触发调用ChannelHandler的userEventTriggered()方法。

我们可以写一个ChannelHandler,重写其userEventTriggered()方法,当客户端发送完业务消息后,空闲时间超过4秒,则该方法会被调用,我们可在这个方法内做向服务端发送心跳消息的逻辑,用来保持和服务端的长连接。

总结

简而言之:IdleStateHandler这个类会根据你设置的超时参数的类型和值,循环去检测channelRead和write方法多久没有被调用了,如果这个时间超过了你设置的值,那么就会触发对应的事件,read触发read,write触发write,all触发all

  • 如果超时了,则会调用userEventTriggered方法,且会告诉你超时的类型
  • 如果没有超时,则会循环定时检测,除非你将IdleStateHandler移除Pipeline