flush行为控制

flush操作负责将ByteBuffer消息写入到SocketChannel中发送给对方。write和flush的作用概括如下:

  • write:将需要写的ByteBuf存储到ChannelOutboundBuffer中
  • flush:从ChannelOutboundBuffer中将需要发送的数据读出来通过Channel发送出去

ChannelOutboundBuffer

ChannelOutboundBuffer类主要用于存储其待处理的出站写请求的内部数据。当Netty调用write时数据不会真正的去发送而是写入到ChannelOutboundBuffer缓存队列,直到调用flush方法Netty才会从ChannelOutboundBuffer取数据发送。

每个Unsafe都会绑定一个ChannelOutboundBuffer,也就是说每个客户端连接上服务端都会创建一个ChannelOutboundBuffer绑定客户端Channel。Netty设计ChannelOutboundBuffer是为了减少TCP缓存的压力提高系统的吞吐率。

(这个ChannelOutboundBuffer应该客户端和服务端都需要创建吧,如果客户端使用的也是Netty的话)

理解flushedEntry、unflushedEntry、tailEntry、flushed

ChannelOutboundBuffer应该是用链表缓存数据,flushedEntry是当前已经被刷新的数据首个元素;unflushedEntry是当前没有被数显的数据的首个元素;tailEntry是链表的最后一个元素。flushed应该flushedEntry到unflushedEntry中的元素个数。在链表中展示其位置:

Entry(flushedEntry) -> … -> Entry(unflushedEntry) -> … -> Entry(tailEntry)

ChannelOutboundBuffer中的数据被flush了,并不代表被写入了。所以flushedEntry到unflushedEntry之间的就是待发送的数据,unflushedEntry到tailEntry就是暂存数据,flushed就是待发送数据个数。正常情况下待发送数据发送完成后会flushedEntry指向unflushedEntry位置,并将unflushedEntry置空。

ChannelOutboundBuffer中的方法

方法如下:

  • addMessage:将数据添加到队列的末尾
  • addFlush:准备待发送的数据,在flush前调用
  • nioBuffers:获取待发送数据,发送数据的时候调用
  • removeBytes:发送完成后调用,删除已成功写入TCP缓存的数据

参考资料

  1. Netty——ChannelHandler之flush行为控制