您好,欢迎来到化拓教育网。
搜索
您的当前位置:首页深入netty09-write和flush为什么分离

深入netty09-write和flush为什么分离

来源:化拓教育网

Pipeline 事件传播

首先,回顾一下Netty中的ChannelPipeline和事件传播机制。ChannelPipeline由一系列ChannelHandler组成,分为入站处理器(ChannelInboundHandler)和出站处理器(ChannelOutboundHandler)。

  • 入站处理器:处理进入的数据,如解码、日志记录等。

  • 出站处理器:处理外出的数据,如编码、写数据到Socket等。

当调用writeAndFlush方法时,数据会在ChannelPipeline中传播,经过所有的出站处理器,最终被发送到网络。

writeAndFlush事件传播分析

writeAndFlush的调用流程如下:

写Buffer队列

write操作并不直接发送数据到网络,而是将数据放入ChannelOutboundBuffer。这是一个链表结构的内部缓冲区,用于暂存待发送的数据。

  • Entry对象:每个待发送的数据项被封装为一个Entry对象,并加入到链表中。

  • 水位线控制ChannelOutboundBuffer通过水位线(高水位和低水位)来控制内存使用,防止溢出。

刷新Buffer队列

flush操作负责将ChannelOutboundBuffer中的数据发送到Socket:

  1. 更新指针flushedEntry指针更新,指向unflushedEntry所指向的数据,unflushedEntry置为null

  2. 发送数据:调用底层的doWrite方法,将数据从内存缓冲区写入到Socket缓冲区。

  3. 自旋锁:使用自旋锁来控制写操作的执行次数,防止长时间占用CPU资源。

ChannelChannelHandlerContext都提供了writeAndFlush方法。

它们的主要区别在于:

  • Channel.writeAndFlush:直接在Channel上调用,适用于通用的写入操作。

  • ChannelHandlerContext.writeAndFlush:在特定的ChannelHandlerContext上调用,可以访问上下文信息,如附加的属性等。

在实际使用中,推荐使用ChannelHandlerContext.writeAndFlush,因为它提供了更多的上下文信息和灵活性。

如何触发事件传播?

  1. write

    当调用 write 方法时,Netty 会将数据添加到一个内部的缓冲区(ChannelBuffer)中。这个过程是异步的,不会立即触发网络 I/O 操作。
  2. flush

    flush 方法负责将内部缓冲区中的数据发送到网络。它会触发底层的 I/O 操作,将缓冲区中的数据写入到 Socket 中。
  3. 事件传播

    writeAndFlush 调用后,Netty 的事件处理机制会将数据写入事件加入到事件队列中。随后,这些事件会被 EventLoop 线程处理,并传播给 ChannelPipeline 中的 ChannelHandler

数据写入 Socket 底层的过程

  1. 数据封装

    开发者通过 write 方法将数据封装到 ChannelBuffer 中。
  2. 数据缓存

    数据首先被缓存在 Netty 的内存中,而不是直接写入 Socket。
  3. 触发写操作

    flush 操作会触发实际的网络写操作,将缓存中的数据发送到底层的 Socket。
  4. Socket 写入

    Netty 通过 Java NIO 的 SocketChannel 将数据写入到操作系统的 Socket 缓冲区。
  5. 操作系统处理

    操作系统负责将 Socket 缓冲区中的数据发送到网络上。

为什么会有 write 和 flush 两个动作?

  • 解耦操作

    • writeflush 的分离允许更细粒度的控制数据的发送过程。

  • 性能优化

    • 通过批量发送数据(即先 write 多个数据到缓冲区,然后一次性 flush),可以减少网络 I/O 操作的次数,提高性能。

  • 灵活性

    • 开发者可以根据需要决定何时发送数据,例如,可以在收到多个消息后再一次性发送,减少网络交互次数。

数据存储和 writeAndFlush 的同步性

  • 内部缓冲

    • 在执行 flush 之前,数据被存储在 Netty 的内部缓冲区中。

  • 同步性

    • writeAndFlush 可以是同步或异步的,取决于 Channel 的配置。如果配置了自动读取(auto-read),writeAndFlush 通常是异步的。如果没有配置自动读取,它将等待数据发送完成再返回。

  • 线程安全

    • writeAndFlush 是线程安全的,可以在多个线程中调用,Netty 内部会处理并发问题。

总结

writeAndFlush 是 Netty 中用于发送数据的组合操作,它先缓存数据,然后触发网络 I/O 操作将数据发送出去。这种设计提高了数据发送的灵活性和性能,同时保证了线程安全。理解 writeflush 的分离以及它们的执行机制,有助于更好地利用 Netty 构建高效的网络应用。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo9.cn 版权所有 赣ICP备2023008801号-1

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务