前语

本篇博文是《从0到1学习 Netty》中实战系列的第二篇博文,主要内容是经过引进心跳检测机制来解决假死衔接问题,避免资源糟蹋和通信失利,往期系列文章请拜访博主的 Netty 专栏,博文中的一切代码悉数收集在博主的 GitHub 仓库中;

假死衔接

在上一篇博文 如何构建多客户端聊天室 中,咱们构建了一个简易的聊天室 demo,然而它还有许多需要优化的当地,本篇博文要讲的是如何及时检测和处理假死衔接,减少资源糟蹋。

那什么是假死衔接呢?假死衔接是指在网络通信中出现的一种状况,其间衔接看似正常但实际上现已失效。

这种状况可能由以下原因引起:

  1. 网络设备毛病:例如网卡、机房等底层设备产生毛病,导致 TCP 衔接断开。尽管底层衔接现已断开,但使用程序没有察觉到,并继续占用资源。
  2. 不稳定的公网网络:假如公网网络存在丢包问题,接连丢包会导致客户端数据发送失利,服务端也无法接收数据,从而形成资源糟蹋。
  3. 使用程序线程堵塞:使用程序线程可能因为某些原因而被堵塞,无法进行数据的读写操作,这会导致衔接状况死板,表面上看衔接正常但实际上无法传输数据。

与假死衔接相关的问题包括:

  1. 无法主动开释占用的资源:因为使用程序未能正确检测到衔接状况的改变,假死衔接会继续占用系统资源,形成资源糟蹋。
  2. 发送超时:当向假死衔接发送数据时,因为衔接已失效,无法成功发送数据,导致发送操作超时。

在 Netty 中会使用处理闲暇状况的处理器 IdleStateHandler 来对假死衔接进行及时检测,并触发相应的事情。闲暇状况指的是衔接或通道在一段时刻内没有进行读取、写入或许读写操作的状况。

闲暇检测

IdleStateHandler 的作用是监测衔接或通道的闲暇状况,并在到达指定的闲暇时刻阈值时触发相应的事情。经过使用 IdleStateHandler,咱们能够轻松地检测和处理闲暇衔接或通道,以便履行特定的操作或许维护衔接的健康状况。

【Netty】「项目实战」(二)提升聊天室的性能,从引入心跳检测机制开始

IdleStateHandler 能够根据需要设置三种类型的闲暇状况:

  1. 读闲暇 READER_IDLE:当在指定的时刻段内没有从衔接中读取到数据时,就会触发读闲暇事情;
  2. 写闲暇 WRITER_IDLE:当在指定的时刻段内没有向衔接中写入数据时,就会触发写闲暇事情;
  3. 读写闲暇 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 事情,如下所示:

【Netty】「项目实战」(二)提升聊天室的性能,从引入心跳检测机制开始

接下来,咱们根据上述原理,完成心跳检测机制。

心跳机制

心跳检测机制是一种常用的网络通信机制,用于检测通信双方是否坚持衔接。它的基本原理是,一方定时向另一方发送一个特殊的数据包,称为心跳包,假如在一定时刻内没有收到回复,就认为对方现已断开。心跳检测机制能够用于检测网络毛病,开释资源,或许测验重连。

为了保证心跳机制的有效性,需要设置适宜的心跳频率。通常状况下,服务器会设置一个 IdleTimeSeconds 参数,表示服务器在多长时刻内没有收到客户端的任何音讯时将视为 READ_IDLE 事情。为了避免此类状况的产生,客户端发送心跳包的频率应小于服务器设置的 IdleTimeSeconds 值。一种常见的做法是将心跳频率设置为 IdleTimeSeconds 的一半,以保证在服务器确定客户端处于闲暇状况之前,客户端现已发送了新的心跳包。

// 服务端
ch.pipeline().addLast(new IdleStateHandler(60, 0, 0));
// 客户端
ch.pipeline().addLast(new IdleStateHandler(0, 30, 0));

运行成果:

【Netty】「项目实战」(二)提升聊天室的性能,从引入心跳检测机制开始

经过施行心跳机制,能够有效地处理非网络相关的 READ_IDLE 事情。它能够供给及时的反应,保证服务器和客户端之间的衔接坚持活泼,同时减少不必要的断开衔接操作,提升系统的稳定性和用户体验。

跋文

总而言之,经过引进心跳检测机制,咱们成功地提升了聊天室的性能。经过定时发送心跳包,服务器能够继续监测与客户端的衔接状况。一旦发现某个衔接长时刻没有响应,服务器会立即采纳相应措施,如封闭该衔接或从头树立衔接,以保证聊天室的稳定性和可靠性。

以上便是提升聊天室的性能,从引进心跳检测机制开端的一切内容了,希望本篇博文对我们有所协助!

参阅:

  • Netty API reference;
  • 黑马程序员Netty全套教程 ;

上篇精讲:「项目实战」(一)如何构建多客户端聊天室

我是,等待你的重视,创造不易,请多多支撑;

公众号:sidiot的技术驿站

系列专栏:探究 Netty:源码解析与使用事例分享