Netty的writeAndFlush流程分析

Netty的writeAndFlush流程分析

1、Write操作

writeAndFlush是一个典型的出站操作,如果调用者是channel则从tail节点向前传播。

 public final ChannelFuture writeAndFlush(Object msg) {
        return tail.writeAndFlush(msg);
   }

看TailContext的writeAndFlush方法。

在这里插入图片描述
会调用write方法,其中flush参数的值为true。
在这里插入图片描述
先调用write方法,传播一个write事件,然后再调用flush方法。

在这里插入图片描述调用HeadContext中的write方法。
在这里插入图片描述
主要进行两步操作,消息过滤,如果使用的不是直接内存需要申请一块直接内存将msg包装一下,然后,添加到channelOutBounfBuffer中,这是一个链表结构。
在这里插入图片描述
因此在传输数据的时候,最好使用DirectByteBuf可以减少一次拷贝。为什么需要这次拷贝呢?因为堆内存是会随着垃圾回收动态变化的,数据拷贝的时候需要保证内存地址不变。
在这里插入图片描述ChannelOutboundBuffer 缓存是一个链表结构,每次传入的数据都会被封装成一个 Entry 对象添加到链表中。ChannelOutboundBuffer 包含三个非常重要的指针:第一个被写到缓冲区的节点 flushedEntry、第一个未被写到缓冲区的节点 unflushedEntry和最后一个节点 tailEntry。

在初始状态下这三个指针都指向 NULL,当我们每次调用 write 方法是,都会调用 addMessage 方法改变这三个指针的指向,可以参考下图理解指针的移动过程会更加形象。
在这里插入图片描述
ChannelOutboundBuffer包装了bytebuf,如果一直往里面写数据,可能会造成OOM,因此Netty里面引入了高低水位,也就是每次写一个entry后,会计算当前的字节数如果超过了高水位,就会设置不可写。
在这里插入图片描述
但是这个不可写的话,需要用户去手动判断 channel.isWriteAble,否则的话,还是可以继续写的。
在这里插入图片描述

2、Flush操作

flush操作就是将缓冲区的数据写到socket缓冲区的过程。将用户缓冲区的数据写到内核缓冲区。

HeadContext的flush:
在这里插入图片描述
在这里插入图片描述
主要包含两个重要方法,addflush和flush0。
addflush用于移动指针,并且减少channelOutBoundBuffer中的字节数。
在这里插入图片描述
当减少到小于低水位的时候,就标记为可写。
在这里插入图片描述
flush0 主要完成刷新的操作,因为数据量可能很大,如果一直写的话,会阻塞netty的work线程,这里引入了一个自选锁:
在这里插入图片描述
如果写完了,需要清除write事件,否则的话,下一轮继续写。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值