一文搞定Netty接收数据的原理

JavaEdge

共 1274字,需浏览 3分钟

 · 2020-12-29


  点击上方“JavaEdge”,关注公众号

设为“星标”,好文章不错过!

1 Netty读数据的技巧




1.1 AdaptiveRecvByteBufAllocator


自适应数据大小的分配器。打水时,拿多大桶去装?

小了不够,大了浪费。所以根据自己实际装预估下次情况,从而决定下次带多大桶。

AdaptiveRecvByteBufAllocator对bytebuf的猜测

  • 直接放大

  • 谨慎缩小( 需连续2次判断)




1.2 defaultMaxMessagesPerRead


连续读。
排队打水时,假设当前桶装满了,这时你会觉得可能还要打点水才够用,所以直接拿个新桶等装,而非回家,直到后面出现

  • 有桶没有装满

  • 装了很多桶了,需要给别人留个机会

等原因才停止,回家。

2 执行流程


如下都是worker线程的事。

多路复用器( Selector )接收到OP_READ事件
处理OP_READ事件:NioSocketChannel.NioSocketChannelUnsafe.read()

  • 分配一个初始1024字节的byte buffer来接受数据

  • 从Channel接受数据到byte buffer

  • 记录实际接受数据大小,调整下次分配byte buffer大小

  • 触发 pipeline.fireChannelRead(byteBuf)把读取到的数据传播出去

  • 判断接受byte buffer是否满载而归:是,尝试继续读取直到没有数据或满16次;否,结束本轮读取,等待下次OP_READ事件


和连接事件类似,我们肯定还是主要在 NioEventLoop

此处先处理的 OP_ACCEPT 建立连接事件,直接让它过了

这次来的才是处理读请求的

3 读取数据的根本 API


sun.nio.ch.SocketChannellmpl#read(java.nio.ByteBuffer)

4 read方法区别


  • NioSocketChannel#read 读数据

  • NioServerSocketChannel#read 创建连接


5 fireChannelRead区别


  • pipeline.fireChannelReadComplete()
    一次读事件处理完成

  • pipeline fireChannelRead(byteBuf)
    一次读数据完成, 一次读事件处理可能会包含多次读数据操作

6 为啥最多只尝试读16次?


给别人留机会。


往期推荐


大厂如何解决数值精度/舍入/溢出问题

大厂数据库事务实践-事务生效就能保证正确回滚?

线上问题事迹(一)数据库事务居然都没生效?

硬核干货:HTTP超时、重复请求必见坑点及解决方案

给大忙人们看的Java NIO教程之Channel





目前交流群已有 800+人,旨在促进技术交流,可关注公众号添加笔者微信邀请进群


喜欢文章,点个“在看、点赞、分享”素质三连支持一下~

浏览 11
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报