前语
本篇博文是《从0到1学习 Netty》中实战系列的第二篇博文,主要内容是经过引进心跳检测机制来解决假死衔接问题,避免资源糟蹋和通信失利,往期系列文章请拜访博主的 Netty 专栏,博文中的一切代码悉数收集在博主的 GitHub 仓库中;
假死衔接
在上一篇博文 如何构建多客户端聊天室 中,咱们构建了一个简易的聊天室 demo,然而它还有许多需要优化的当地,本篇博文要讲的是如何及时检测和处理假死衔接,减少资源糟蹋。
那什么是假死衔接呢?假死衔接是指在网络通信中出现的一种状况,其间衔接看似正常但实际上现已失效。
这种状况可能由以下原因引起:
- 网络设备毛病:例如网卡、机房等底层设备产生毛病,导致 TCP 衔接断开。尽管底层衔接现已断开,但使用程序没有察觉到,并继续占用资源。
- 不稳定的公网网络:假如公网网络存在丢包问题,接连丢包会导致客户端数据发送失利,服务端也无法接收数据,从而形成资源糟蹋。
- 使用程序线程堵塞:使用程序线程可能因为某些原因而被堵塞,无法进行数据的读写操作,这会导致衔接状况死板,表面上看衔接正常但实际上无法传输数据。
与假死衔接相关的问题包括:
- 无法主动开释占用的资源:因为使用程序未能正确检测到衔接状况的改变,假死衔接会继续占用系统资源,形成资源糟蹋。
- 发送超时:当向假死衔接发送数据时,因为衔接已失效,无法成功发送数据,导致发送操作超时。
在 Netty 中会使用处理闲暇状况的处理器 IdleStateHandler
来对假死衔接进行及时检测,并触发相应的事情。闲暇状况指的是衔接或通道在一段时刻内没有进行读取、写入或许读写操作的状况。
闲暇检测
IdleStateHandler
的作用是监测衔接或通道的闲暇状况,并在到达指定的闲暇时刻阈值时触发相应的事情。经过使用 IdleStateHandler
,咱们能够轻松地检测和处理闲暇衔接或通道,以便履行特定的操作或许维护衔接的健康状况。
IdleStateHandler
能够根据需要设置三种类型的闲暇状况:
- 读闲暇
READER_IDLE
:当在指定的时刻段内没有从衔接中读取到数据时,就会触发读闲暇事情; - 写闲暇
WRITER_IDLE
:当在指定的时刻段内没有向衔接中写入数据时,就会触发写闲暇事情; - 读写闲暇
ALL_IDLE
:当在指定的时刻段内既没有读取到数据,也没有写入数据时,就会触发读写闲暇事情。
当指定时刻内未产生读或写事情时,会触发特定事情,代码如下所示:
ch.pipeline().addLast(new IdleStateHandler(0, 0, 60));
ch.pipeline().addLast(new ChannelDuplexHandler() {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent e = (IdleStateEvent) evt;
if (e.state() == IdleState.READER_IDLE) {
ctx.close();
} else if (e.state() == IdleState.WRITER_IDLE) {
ctx.writeAndFlush(new PingMessage());
}
}
}
});
在上面的示例中,咱们将 IdleStateHandler
添加到通道的管道中,并设置了读写都闲暇的时刻阈值为60秒。当衔接或通道60秒内没有读取或写入操作时,IdleStateHandler
会触发 IdleStateEvent
事情。
为了便利展示,将 IdleStateHandler
设置为假如5秒内未读到数据,则会触发 READ_IDLE
事情,如下所示:
接下来,咱们根据上述原理,完成心跳检测机制。
心跳机制
心跳检测机制是一种常用的网络通信机制,用于检测通信双方是否坚持衔接。它的基本原理是,一方定时向另一方发送一个特殊的数据包,称为心跳包,假如在一定时刻内没有收到回复,就认为对方现已断开。心跳检测机制能够用于检测网络毛病,开释资源,或许测验重连。
为了保证心跳机制的有效性,需要设置适宜的心跳频率。通常状况下,服务器会设置一个 IdleTimeSeconds
参数,表示服务器在多长时刻内没有收到客户端的任何音讯时将视为 READ_IDLE
事情。为了避免此类状况的产生,客户端发送心跳包的频率应小于服务器设置的 IdleTimeSeconds
值。一种常见的做法是将心跳频率设置为 IdleTimeSeconds
的一半,以保证在服务器确定客户端处于闲暇状况之前,客户端现已发送了新的心跳包。
// 服务端
ch.pipeline().addLast(new IdleStateHandler(60, 0, 0));
// 客户端
ch.pipeline().addLast(new IdleStateHandler(0, 30, 0));
运行成果:
经过施行心跳机制,能够有效地处理非网络相关的 READ_IDLE
事情。它能够供给及时的反应,保证服务器和客户端之间的衔接坚持活泼,同时减少不必要的断开衔接操作,提升系统的稳定性和用户体验。
跋文
总而言之,经过引进心跳检测机制,咱们成功地提升了聊天室的性能。经过定时发送心跳包,服务器能够继续监测与客户端的衔接状况。一旦发现某个衔接长时刻没有响应,服务器会立即采纳相应措施,如封闭该衔接或从头树立衔接,以保证聊天室的稳定性和可靠性。
以上便是提升聊天室的性能,从引进心跳检测机制开端的一切内容了,希望本篇博文对我们有所协助!
参阅:
- Netty API reference;
- 黑马程序员Netty全套教程 ;
上篇精讲:「项目实战」(一)如何构建多客户端聊天室
我是,等待你的重视,创造不易,请多多支撑;
公众号:sidiot的技术驿站;
系列专栏:探究 Netty:源码解析与使用事例分享