Netty+SpringBoot+FastDFS+Html5实现聊天App(六)

10次阅读

共计 1878 个字符,预计需要花费 5 分钟才能阅读完成。

Netty+SpringBoot+FastDFS+Html5 实现聊天 App,项目介绍。
Netty+SpringBoot+FastDFS+Html5 实现聊天 App,项目 github 链接。
本章完整代码链接。
本章将给聊天 App_PigChat 加上心跳机制。

为什么要实现心跳机制
如果没有特意的设置某些选项或者实现应用层心跳包,TCP 空闲的时候是不会发送任何数据包。也就是说,当一个 TCP 的 socket,客户端与服务端谁也不发送数据,会一直保持着连接。这其中如果有一方异常掉线(例如死机、路由被破坏、防火墙切断连接等),另一端如果没有发送数据,永远也不可能知道。这对于一些服务型的程序来说,是灾难性的后果,将会导致服务端 socket 资源耗尽。
举个简单的例子,当我们因为特殊情况打开飞行模式,在处理完事件之后再关闭飞行模式,这时候如果再进入应用程序中,我们将以新的 channel 进入,但是之前的 channel 还是会保留。
因此,为了保证连接的有效性、及时有效地检测到一方的非正常断开,保证连接的资源被有效的利用,我们就会需要一种保活的机制,通常改机制两种处理方式:
1、利用 TCP 协议层实现的 Keepalive;
2、自己在应用层实现心跳包。

实现心跳机制
新建一个 HeartBeatHandler 用于检测 channel 的心跳。
继承 ChannelInboundHandlerAdapter,并重写其 userEventTriggered 方法。当客户端的所有 ChannelHandler 中 4s 内没有 write 事件,则会触发 userEventTriggered 方法。
首先我们判断 evt 是否是 IdleStateEvent 的实例,IdleStateEvent 用于触发用户事件,包含读空闲 / 写空闲 / 读写空闲。
对 evt 进行强制履行转换后,通过 state 判断其状态,只有当其该 channel 处于读写空闲的时候才将这个 channel 关闭。
/**
* @Description: 用于检测 channel 的心跳 handler
* 继承 ChannelInboundHandlerAdapter,从而不需要实现 channelRead0 方法
*/
public class HeartBeatHandler extends ChannelInboundHandlerAdapter {

@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {

// 判断 evt 是否是 IdleStateEvent(用于触发用户事件,包含 读空闲 / 写空闲 / 读写空闲)
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent)evt; // 强制类型转换

if (event.state() == IdleState.READER_IDLE) {
System.out.println(“ 进入读空闲 …”);
} else if (event.state() == IdleState.WRITER_IDLE) {
System.out.println(“ 进入写空闲 …”);
} else if (event.state() == IdleState.ALL_IDLE) {

System.out.println(“channel 关闭前,users 的数量为:” + ChatHandler.users.size());

Channel channel = ctx.channel();
// 关闭无用的 channel,以防资源浪费
channel.close();

System.out.println(“channel 关闭后,users 的数量为:” + ChatHandler.users.size());
}
}

}

}

增加心跳支持
在原来的 WSServerInitialzer 中增加心跳机制的支持。

// ====================== 增加心跳支持 start ======================
// 针对客户端,如果在 1 分钟时没有向服务端发送读写心跳 (ALL),则主动断开
// 如果是读空闲或者写空闲,不处理
pipeline.addLast(new IdleStateHandler(8, 10, 12));
// 自定义的空闲状态检测
pipeline.addLast(new HeartBeatHandler());
// ====================== 增加心跳支持 end ======================

正文完
 0