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秒內如果客戶端沒輸入東西,服務端也沒發東西,就會觸發讀寫超時事件。
測試是成功的。