Netty是如何写数据的?

举报
JavaEdge 发表于 2021/06/04 01:26:02 2021/06/04
【摘要】 1 写数据的核心问题 快递场景(包裹)Netty写数据(数据)揽收到仓库write:写到一个buffer从仓库发货flush:把buffer里的数据发送出去揽收到仓库并立马发货( 加急件)writeAndFlush: 写到buffer, 立马发送揽收与发货之间有个缓冲的仓库Write和Flush之间有个ChannelOutboundBuffer 1.1 写炸了 对方...

1 写数据的核心问题

快递场景(包裹) Netty写数据(数据)
揽收到仓库 write:写到一个buffer
从仓库发货 flush:把buffer里的数据发送出去
揽收到仓库并立马发货( 加急件) writeAndFlush: 写到buffer, 立马发送
揽收与发货之间有个缓冲的仓库 Write和Flush之间有个ChannelOutboundBuffer

1.1 写炸了

  • 对方仓库爆仓时,送不了的时候,会停止送,协商等电话通知什么时候好了,再送。
    Netty写数据,写不进去时,会停止写,然后注册一个 OP_WRITE事件,来通知什么时候可以写进去了再写。

1.2 挺能写的

  • 发送快递时,对方仓库都直接收下,这个时候再发送快递时,可以尝试发送更多的快递试试,这样效果更好。
    Netty批量写数据时,如果尝试写的都写进去了,接下来会尝试写更多(调整maxBytesPerGatheringWrite)

1.3 我还能写

  • 发送快递时,发到某个地方的快递特别多,我们会连续发,但是快递车毕竟有限,也会考虑下其他地方

  • Netty只要有数据要写,且能写的出去,则一直尝试,直到写不出去或满16次(writeSpinCount)

写16次还没有写完,就直接 schedule 一个 task 来继续写,而不是用注册写事件来触发,更简洁有力。

1.4 写不过来了

  • 揽收太多,发送来不及时,爆仓,这个时候会出个告示牌:收不下了,最好过2天再来邮寄吧。
  • Netty待写数据太多,超过一定的水位线(writeBufferWaterMark.high()) ,会将可写的标志位改成 false,让应用端自己做决定要不要发送数据(写)了(很真实,将责任推给用户)。

2 核心流程

  • Write - 写数据到buffer :
    ChannelOutboundBuffer#addMessage

  • Flush -发送buffer里面的数据:
    AbstractChannel.AbstractUnsafe#flush

    • 准备数据: ChannelOutboundBuffer#addFlush
  • 写完了更新状态

    • 发送: NioSocketChannel#doWrite

3 写数据的根本

  • Single write
    sun.nio.ch.SocketChannelmpl#write(java.nio.ByteBuffer)
  • gathering write(批量写)
    sun.nio.ch.SocketChannelmpl#write(java.nio.ByteBuffer[], int, int)

写数据写不进去时,会停止写,注册一个 OP_WRITE 事件,来通知什么时候可以写进去了。
OP_WRITE不代表有数据可写,而是可以写进去,所以正常情况下不要注册它,否则会一直触发。

  • channelHandlerContext.channel().write()
    从TailContext开始执行
  • channelHandlerContext.write()
    从当前的Context开始

文章来源: javaedge.blog.csdn.net,作者:JavaEdge.,版权归原作者所有,如需转载,请联系作者。

原文链接:javaedge.blog.csdn.net/article/details/111599726

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。