Netty大战之Netty 心跳(heartbeat)服务源码剖析

源码剖析目的

 Netty提供的心跳介绍

 源码剖析:

IdleStateHandler四个重要属性

需要注意:为什么考虑超时的问题还要考虑,出栈慢的问题,传输过程比较慢,连接状态还是存在的,但是指定的时间由于出栈慢导致消息传输出现了问题。

 handlerAdded方法

当handler被添加到Pipeline中时,则handlerAdded方法内部会调用的initilize方法

 下面的是initilize方法

 IdleStateHandler类的三个定时任务

 AbstractIdleTask

友情提示:当通道关闭了,就不执行任务了。如果通道没有关闭就执行子类的run方法。就是我们自定义上面的三个定时任务。实际就是写handlerAdded方法。

 读事件ReaderIdleTimeoutTask事件分析

debug准备工作

友情提示:ReaderIdleTimeoutTask继承AbstractIdleTask,其他的写任务和读写任务都是继承该父类

其他两个分析的过程和该方法分析是一样的

ReaderIdleTimeoutTask代码:

 private final class ReaderIdleTimeoutTask extends AbstractIdleTask {

        ReaderIdleTimeoutTask(ChannelHandlerContext ctx) {
            super(ctx);
        }

        @Override
        protected void run(ChannelHandlerContext ctx) {
            long nextDelay = readerIdleTimeNanos;
            if (!reading) {
                nextDelay -= ticksInNanos() - lastReadTime;
            }

            if (nextDelay <= 0) {
                // Reader is idle - set a new timeout and notify the callback.
                readerIdleTimeout = schedule(ctx, this, readerIdleTimeNanos, TimeUnit.NANOSECONDS);

                boolean first = firstReaderIdleEvent;
                firstReaderIdleEvent = false;

                try {
                    IdleStateEvent event = newIdleStateEvent(IdleState.READER_IDLE, first);
                    channelIdle(ctx, event);
                } catch (Throwable t) {
                    ctx.fireExceptionCaught(t);
                }
            } else {
                // Read occurred before the timeout - set a new timeout with shorter delay.
                readerIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);
            }
        }
    }

 说明:

 WriterIdleTimeoutTask源码:

private final class WriterIdleTimeoutTask extends AbstractIdleTask {

        WriterIdleTimeoutTask(ChannelHandlerContext ctx) {
            super(ctx);
        }

        @Override
        protected void run(ChannelHandlerContext ctx) {

            long lastWriteTime = IdleStateHandler.this.lastWriteTime;
            long nextDelay = writerIdleTimeNanos - (ticksInNanos() - lastWriteTime);
            if (nextDelay <= 0) {
                // Writer is idle - set a new timeout and notify the callback.
                writerIdleTimeout = schedule(ctx, this, writerIdleTimeNanos, TimeUnit.NANOSECONDS);

                boolean first = firstWriterIdleEvent;
                firstWriterIdleEvent = false;

                try {
                    if (hasOutputChanged(ctx, first)) {
                        return;
                    }

                    IdleStateEvent event = newIdleStateEvent(IdleState.WRITER_IDLE, first);
                    channelIdle(ctx, event);
                } catch (Throwable t) {
                    ctx.fireExceptionCaught(t);
                }
            } else {
                // Write occurred before the timeout - set a new timeout with shorter delay.
                writerIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);
            }
        }
    }

 说明:

AllIdleTimeoutTask源码

 private final class AllIdleTimeoutTask extends AbstractIdleTask {

        AllIdleTimeoutTask(ChannelHandlerContext ctx) {
            super(ctx);
        }

        @Override
        protected void run(ChannelHandlerContext ctx) {

            long nextDelay = allIdleTimeNanos;
            if (!reading) {
                nextDelay -= ticksInNanos() - Math.max(lastReadTime, lastWriteTime);
            }
            if (nextDelay <= 0) {
                // Both reader and writer are idle - set a new timeout and
                // notify the callback.
                allIdleTimeout = schedule(ctx, this, allIdleTimeNanos, TimeUnit.NANOSECONDS);

                boolean first = firstAllIdleEvent;
                firstAllIdleEvent = false;

                try {
                    if (hasOutputChanged(ctx, first)) {
                        return;
                    }

                    IdleStateEvent event = newIdleStateEvent(IdleState.ALL_IDLE, first);
                    channelIdle(ctx, event);
                } catch (Throwable t) {
                    ctx.fireExceptionCaught(t);
                }
            } else {
                // Either read or write occurred before the timeout - set a new
                // timeout with shorter delay.
                allIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);
            }
        }
    }
}

说明:

 心跳机制总结:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Netty是一个开源的Java网络编程框架,支持多种协议和高性能的网络通信。而WebSocket是一种基于HTTP的协议,能够在浏览器和服务器之间建立全双工通信通道,实现实时的数据传输。在实际开发中,我们常常需要使用Netty来实现WebSocket连接,并通过“心跳”机制来保持连接的稳定性。 “心跳”机制是指在WebSocket连接中,服务器定期向客户端发送特定信息(如一段规定的文本),以检测和保持连接的活跃状态。当客户端接收到心跳消息时,也需要及时回复一个响应消息,以确认连接的正常状态。通过这种方式,可以有效避免长时间未传输数据导致连接失效的情况。 在Netty中,我们可以使用IdleStateHandler类来实现心跳机制。该类可以设置检测的时间间隔和失败次数等参数,并通过自定义ChannelInboundHandler子类的实现来处理空闲超时及心跳消息的发送和接收逻辑。 下面是一个示例代码: ``` public class WebSocketIdleStateHandler extends IdleStateHandler { public WebSocketIdleStateHandler(int readerIdleTimeSeconds, int writerIdleTimeSeconds, int allIdleTimeSeconds) { super(readerIdleTimeSeconds, writerIdleTimeSeconds, allIdleTimeSeconds); } @Override protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception { // 发送心跳消息 TextWebSocketFrame heartbeat = new TextWebSocketFrame("heartbeat"); ctx.writeAndFlush(heartbeat); } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof WebSocketFrame) { // 接收心跳消息并回复响应消息 WebSocketFrame frame = (WebSocketFrame) evt; if (frame instanceof TextWebSocketFrame && ((TextWebSocketFrame) frame).text().equals("heartbeat")) { TextWebSocketFrame response = new TextWebSocketFrame("response"); ctx.writeAndFlush(response); } } else { super.userEventTriggered(ctx, evt); } } } ``` 以上代码实现了一个WebSocketIdleStateHandler类,继承自NettyIdleStateHandler类,用于定时检测连接状态并发送/接收心跳消息。在channelIdle方法中,我们创建一个TextWebSocketFrame对象作为心跳消息,并将其写入到ChannelHandlerContext中。在userEventTriggered方法中,我们判断收到的WebSocketFrame类型是否为TextWebSocketFrame,并检查其内容是否为“heartbeat”。如果是,则认为收到了心跳消息,创建一个响应对象TextWebSocketFrame,将其写入到ChannelHandlerContext中。这样就能保持WebSocket连接的稳定性和实时性了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

越来越没意思

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值