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缓存的数据