Netty系列文章 - 心跳检测
本章暂且先不讨论Netty源码是怎么实现的,先看一下Netty心跳检测的应用.
科普基础
- 心跳机制
- 心跳是在TCP长连接中,客户端和服务端定时向对方发送数据包通知对方自己还在线,保证连接的有效性的一种机制
- 在服务器和客户端之间一定时间内没有数据交互时, 即处于 idle 状态时, 客户端或服务器会发送一个特殊的数据包给对方, 当接收方收到这个数据报文后, 也立即发送一个特殊的数据报文, 回应发送方, 此即一个 PING-PONG 交互. 自然地, 当某一端收到心跳消息后, 就知道了对方仍然在线, 这就确保 TCP 连接的有效性
- 心跳实现
- 使用TCP协议层的Keeplive机制,但是该机制默认的心跳时间是2小时,依赖操作系统实现不够灵活
- 应用层实现自定义心跳机制,比如Netty实现心跳机制
快速开始
Server
/**
* @author Itachi is.xianglei@gmail.com
* @Date 2020-01-03 15:56
*/
public class Server {
@SneakyThrows
public static void main(String[] args) {
// 主线程
EventLoopGroup master = new NioEventLoopGroup(1);
// 工作线程
EventLoopGroup slave = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(master,slave)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new StringDecoder(Charset.defaultCharset()));
pipeline.addLast(new DelimiterBasedFrameDecoder(4096, Delimiters.lineDelimiter()));
/**
* 10: 10秒后进入读空闲
* 15: 15秒后进入写空闲
* 30: 30秒后进入读写空闲
*/
pipeline.addLast(new IdleStateHandler(10,15,30, TimeUnit.SECONDS));
/**
* 自定义的心跳检测处理器
*/
pipeline.addLast(new HeartBeatHandler());
/**
* 自定义的消息处理器
*/
pipeline.addLast(new MyHandler());
}
});
ChannelFuture channelFuture = bootstrap.bind("127.0.0.1", 9090).sync();
channelFuture.channel().closeFuture();
}
}
MyHandler
/**
* @author Itachi is.xianglei@gmail.com
* @Date 2020-01-03 16:06
*/
public class MyHandler extends SimpleChannelInboundHandler<String> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
Channel channel = ctx.channel();
SocketAddress socketAddress = channel.remoteAddress();
System.out.println(socketAddress + "->发来消息: "+msg);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
SocketAddress socketAddress = ctx.channel().remoteAddress();
System.out.println(socketAddress+"<-已上线!");
}
}
HeartBeatHandler
/**
* @author Itachi is.xianglei@gmail.com
* @Date 2020-01-03 16:32
*/
public class HeartBeatHandler extends ChannelInboundHandlerAdapter {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
// 读空闲
if (IdleState.READER_IDLE == event.state()) {
System.out.println("进入读空闲...");
}
// 写空闲
if (IdleState.WRITER_IDLE == event.state()) {
System.out.println("进入写空闲...");
}
// 读写空闲
if (IdleState.ALL_IDLE == event.state()) {
System.out.println("进入读写空闲,即将断开与客户端连接...");
ctx.channel().close();
System.out.println("断开连接!");
}
}
}
}
客户端连接工具
推测: 在我们配置的读写时间内.我们客户端不往服务端发送数据,超过10秒,就会进入读空闲.
服务端不往客户端发送数据超过15秒就会进入写空闲, 在30秒内,不写不读的情况下…会一直进行心跳检测…
超过30秒后则会进入读写空闲,并关闭客户端的连接…
控制台输出
如有疑问,欢迎留言.