美文网首页
Netty空闲检测之写空闲

Netty空闲检测之写空闲

作者: 赵信信官属 | 来源:发表于2020-11-24 23:18 被阅读0次

在之前的文章,我们介绍了Netty空闲检测之读空闲,以及为了介绍此篇文章,我们也特意写了一篇关于写操作的概括文章.读者对于Netty如何进行写操作也有了一个大概的认识了,接下来我们说一下,对于如何检测写空闲,Netty是如何控制的?

我们在向Pipeline中添加Handler的时候,绝大多数都会添加如下几个Handler.


image.png

分别是编码器(把写入外部地数据进行编码),解码器(把从外部读取地数据进行解码),空闲检测(检测是否读/写空闲),连接管理(如果存在空闲连接,如何处理),业务处理器(处理业务)

假如网络中发送过来一些数据,当这些数据被Netty读取,经过解码器解码之后,空闲检测中的读空闲拿到的数据,一定是一个完整的包含业务含义的数据(对象).然而,写操作就不是这样'完整'了.业务处理器向Netty写入一个数据(对象)之后,Netty可能只是暂时把一部分数据写入了Netty的缓冲区,另一部分写到了TCP缓冲区.

image.png

如上图所示,业务线程向Netty写入一个'HelloWorld'数据,可是会存在,Hello被写入到了TCP缓冲区,而World还在Netty的缓冲区中.当然这种情况一定会发生,但不是一直发生.

在线程池的知识里,有Future对象,我们可以调用get()方法获取任务的结果,但是这样会阻塞调用get()方法的线程(假如任务还没有完成).而Netty优化了这一方面,使得Netty是异步执行任务的.

image.png

要想实现和使用Netty的异步任务执行,必须按照上面的逻辑图码代码. 将业务线程抽离出来,只负责业务上的逻辑,具体的写操作由IO线程来完成,而且业务线程和IO线程都有一个队列,业务线程向IO线程的队列中放入写任务就返回,IO线程完成写之后,向业务线程的队列中放入一个通知任务,业务线程会及时感知到这个通知任务,然后调用业务线程之前设置的监听回调方法.我们直接看下IdleStateHandler类的源码是如何体现的.

// 源码位置: io.netty.handler.timeout.IdleStateHandler#write

@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
    if (writerIdleTimeNanos > 0 || allIdleTimeNanos > 0) {
        // 业务线程在执行写入的时候,最终会将写操作封装成一个写任务放入IO线程的队列中.同时它会设置一个监听,用于回调使用. 
        ctx.write(msg, promise.unvoid()).addListener(writeListener);
    } else {
        ctx.write(msg, promise);
    }
}

private final ChannelFutureListener writeListener = new ChannelFutureListener() {
    @Override
    public void operationComplete(ChannelFuture future) throws Exception {
        lastWriteTime = ticksInNanos();
        firstWriterIdleEvent = firstAllIdleEvent = true;
    }
};

以上说了这些都是和写操作有关,也和空闲检测之写空闲有关.下面我们来分析写空闲如何控制的.

image.png

A点是我们上次写空闲的检测时间点,B点是我们最后一次写操作的时间点,假如此时触发了写空闲检测,时间点在C点.

image.png

而B到C之间的时间长度并没有超过一个空闲检测的时间步长L(正如读空闲有个空闲检测的时间步长一样,写空闲也有一个空闲检测的时间步长),因为A到C之间才是一个时间步长L,因此空闲检测需要继续等待,但是,下一次的空闲检测不能是长度L了,而是A到B的时间长度,相当于在B到C这个时间段我已经检测了,现在只是不足一个时间步长L,我顶多再补偿剩下的时间就可以,因此下次的空闲检测时间步长是(B-A)的长度.


image.png

假如这个时候,空闲检测到了D点,还是没有发生写操作完成.此时B到D之间已经是一个完整的时间步长L了.但是呢,我们并不能说此时没有写操作.上面我们也说了,Netty有可能在缓慢地将数据从Netty的缓冲区写入到TCP的缓冲区,因为只有一个完整的数据写完,才能执行回调,更新最新的写操作时间.接下来空闲检测就会按照步长L的长度,再进行检测.至于我们是否要考虑刚才这种情况,Netty也是在我们构造IdleStateHandler类的时候可以传入一个observeOutput属性用于是否开启.默认是关闭的.

// 源码位置: io.netty.handler.timeout.IdleStateHandler.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) {
            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 {
            writerIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);
        }
    }
}

公众号 Netty历险记

相关文章

  • Netty空闲检测之写空闲

    在之前的文章,我们介绍了Netty空闲检测之读空闲,以及为了介绍此篇文章,我们也特意写了一篇关于写操作的概括文章....

  • Netty空闲检测之读空闲

    客户端与服务端通信的时候,服务端如何感知到客户端下线.客户端可以每4秒向服务端发送一个数据,服务端每5秒进行空闲检...

  • Netty写操作的一点概括

    相对于读操作而言,Netty在处理写操作上更复杂一些.在之前的文章我们介绍了Netty空闲检测之读空闲,为了介绍N...

  • Netty集成心跳检测及其源码

    netty集成心跳检测 需要在pipline里面添加netty自带的心跳检测 实现一个方法来处理当发生上述几种空闲...

  • 空闲

    突如其来的空闲,让我有点儿不知所措。 小暖自打断奶后,每天中午有两个小时的午睡时间。这两个小时,于我来说,简直天堂...

  • 空闲…

    在忙碌中抬头 偶然发现不经意的美--小花花 仿佛世界上有了花才使世界变得美了 以后要在家中要养好多好多的花和绿植呀~

  • 空闲

    每天好像都给自己定了好多目标,但是目标却好像从没有实现过,终究自己还是太懒。 可是每当闲时,自己脑海中想的却也是全...

  • 空闲

    突如其来的一段空闲,有点措手不及。 彷徨,纠结,哀怨,防备,揣测,自勉,各种情绪一哄而上。 我对自己说:淡定,你有...

  • 空闲

    忙忙碌碌的,难得有空闲的时间,闲下来一时也不知该做些什么。平时上班的时间一般是毫无空隙地工作,下班后又急急忙忙地奔...

  • 空闲

    空闲 每个人都有空闲的时候,如果你空闲的时候你会选择做什么了?我们工作是做销售,经常出差,有时候在店里非常空闲,有...

网友评论

      本文标题:Netty空闲检测之写空闲

      本文链接:https://www.haomeiwen.com/subject/shwwiktx.html