心跳检测机制

心跳机制是定时发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保连接的有效性的机制。

实例要求:

  1. 编写一个 Netty心跳检测机制案例, 当服务器超过3秒没有读时,就提示读空闲
  2. 当服务器超过5秒没有写操作时,就提示写空闲
  3. 实现当服务器超过7秒没有读或者写操作时,就提示读写空闲

服务端

image-20201113152708502

服务端添加IdleStateHandler心跳检测处理器,并添加自定义处理Handler类实现userEventTriggered()方法作为超时事件的逻辑处理;

  • long readerIdleTime:表示多长时间没有读,就会发送一个心跳检测包检测是否连接(读空闲)
  • long writerIdleTime:表示多长时间没有写,就会发送一个心跳检测包检测是否连接(写空闲)
  • long allIdleTime:表示多长时间没有读写,就会发送一个心跳检测包检测是否连接 (读写空闲)

当IdleStateEvent触发后,就会传递给管道的下一个handler去处理。通过调用下一个handler的userEventTriggered方法。

image-20201113153849666

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class MyServer {

public static void main(String[] args) {
//创建两个线程组
NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
NioEventLoopGroup workerGroup = new NioEventLoopGroup(8);

try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {

@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//加入一个netty 提供IdleStateHandler
//long readerIdleTime:表示多长时间没有读,就会发送一个心跳检测包检测是否连接(读空闲)
//long writerIdleTime:表示多长时间没有写,就会发送一个心跳检测包检测是否连接(写空闲)
//long allIdleTime:表示多长时间没有读写,就会发送一个心跳检测包检测是否连接 (读写空闲)
//当IdleStateEvent触发后,就会传递给管道的下一个handler去处理。通过调用下一个handler的userEventTriggered方法
pipeline.addLast(new IdleStateHandler(3, 5, 7, TimeUnit.SECONDS));
//加入一个对空闲检测进一步处理对handler(自定义)
pipeline.addLast(new MyServerHandler());
}
});

//启动服务器
ChannelFuture channelFuture = bootstrap.bind(7000).sync();

channelFuture.channel().closeFuture().sync();

} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class MyServerHandler extends ChannelInboundHandlerAdapter {


/**
* @param ctx 上下文
* @param evt 事件
* @throws Exception
*/
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
//将evt向下转型IdleStateEvent
IdleStateEvent event = (IdleStateEvent) evt;
String eventType = null;
switch (event.state()) {
case READER_IDLE:
eventType = "读空闲";
break;
case WRITER_IDLE:
eventType = "写空闲";
break;
case ALL_IDLE:
eventType = "读写空闲";
break;
}
System.out.println(ctx.channel().remoteAddress() + eventType + "事件发生");
System.out.println("服务器做相应处理....");
}
}
}

测试

客户端这里就不专门单独写一个了。使用上篇的客户端。https://www.kylin.show/25178.html

CleanShot 2020-11-13 at 16.13.20

服务器啥都不做

3秒钟触发读空闲事件

5秒钟触发写空闲事件

7秒钟触发读写空闲事件