-
Notifications
You must be signed in to change notification settings - Fork 0
6 Heartbeat
BladeCode edited this page Nov 23, 2019
·
1 revision
服务器上的集群服务(zookeeper 或者其他的应用服务),或者是客户端与服务端之间的长连接
- 对于服务器上的这些服务与服务之间,节点与节点之间的通信(无一例外都使用 TCP 连接通信),节点之间的通信如何保证(A 节点感知到 B 或者其他节点是未宕机),此时就需要心跳来检测对应的服务或节点还是正常的
- 对于客户端与服务器之间由于网络问题,或者客户端开启飞行模式,或者关机等状态,服务端是无法感知,因此也需要借助心跳来检测客户端是否关机或开启了飞行模式
通过下面的示例,来学习 Netty 相关的心跳处理
服务启动类,程序入口
public static void main(String[] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
// handler() 与 childHandler() 的区别
// 服务端可以使用 handler() 或者 childHandler(),而对于客户端,一般只使用handler()
// handler()对于处理的 bossGroup 相关的信息,比如链接后,输出日志
// childHandler() 是指连接丢给 workerGroup 之后,对 workerGroup 的 NIO 线程作用
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new HeartbeatServerInitializer());
ChannelFuture channelFuture = serverBootstrap.bind(4321).sync();
channelFuture.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
自定义服务初始化
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// netty 提供的一个空闲状态检查的 handler(IdleStateHandler)
pipeline.addLast(new IdleStateHandler(5, 7, 10, TimeUnit.SECONDS));
// 自定义服务处理器
pipeline.addLast("HeartbeatServerHandler", new HeartbeatServerHandler());
}
public class HeartbeatServerHandler extends ChannelInboundHandlerAdapter {
/**
* 触发某一个事件后被调用
*
* @param ctx 通道处理上下文
* @param evt 事件
* @throws Exception 异常
*/
@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 = "读空闲(超过指定时间,客户端没有向服务器发送任何数据)";
break;
case WRITER_IDLE:
eventType = "写空闲(超过指定时间,服务器没有写任何信息)";
break;
case ALL_IDLE:
eventType = "读写空闲(超过指定时间,没有写或者没有读二者之一,即触发读写空闲)";
break;
default:
break;
}
System.out.println(ctx.channel().remoteAddress() + "超时事件:" + eventType);
ctx.channel().closeFuture();
}
}
}
可直接使用 Socket 中的客户端代码