intro
多个微服务之间,需要通过心跳来判断服务到底还是不是活着。
netty可以轻松地完成心跳连接的逻辑。
这时我们要介绍一个handler:IdleStateHandler
/**
* Triggers an {@link IdleStateEvent} when a {@link Channel} has not performed
* read, write, or both operation for a while.
*/
如果一个channel没有读或者没有写或者两者都没有,就会触发一个IdleStateEvent
。
在IdleStateEvent
这个类中,有一个保存空闲状态的属性:
private final IdleState state;
空闲状态一共有三种:
/**
* An {@link Enum} that represents the idle state of a {@link Channel}.
*/
public enum IdleState {
/**
* No data was received for a while.
*/
READER_IDLE,
/**
* No data was sent for a while.
*/
WRITER_IDLE,
/**
* No data was either received or sent for a while.
*/
ALL_IDLE
}
server
服务端还是模板代码:
public class TestHeartBeatServer {
public static void main(String[] args) throws Exception{
EventLoopGroup bossGroup=new NioEventLoopGroup();
EventLoopGroup workerGroup=new NioEventLoopGroup();
try{
ServerBootstrap serverBootstrap=new ServerBootstrap();
serverBootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).
handler(new LoggingHandler(LogLevel.INFO)).
childHandler(new TestHeartBeatServerInitializer());
ChannelFuture channelFuture=serverBootstrap.bind(8899).sync();
channelFuture.channel().closeFuture().sync();
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
初始化器:
public class TestHeartBeatServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new IdleStateHandler(5,7,0, TimeUnit.SECONDS));
pipeline.addLast(new TestHeartBeatServerHandler());
}
}
new IdleStateHandler(5,7,0, TimeUnit.SECONDS)
5表示如果客户端5秒内没有发送消息,就会触发读超时事件;
7表示如果服务端7秒内没有向客户端发送消息,就会触发写超时事件;
0表示暂时不要读写超时。
我们将自定义handler将以上的信息打印出来:
public class TestHeartBeatServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
String eventType = null;
switch (event.state()) {
case READER_IDLE:
eventType = "read idle";
break;
case WRITER_IDLE:
eventType = "write idle";
break;
case ALL_IDLE:
eventType = "read write idle";
break;
}
System.out.println(ctx.channel().remoteAddress() + "---idle event :" + eventType);
ctx.channel().close();
}
}
}
test
启动server。
使用telnet连接:
5秒钟什么都不输入,服务端就会给出读超时异常:
再连一次,如果客户端不断输入东西:
此时不会有读超时。
服务端7秒内没有写出东西(我们没有写这个逻辑),所以7秒后就会:
现在我们要触发读写超时:
new IdleStateHandler(5,7,0, TimeUnit.SECONDS)
将0改成3。
意思是,3秒内如果客户端没输入东西,服务端也没发东西,就会触发读写超时事件。
测试是成功的。