Netty源码解读-EventLoop(二)
创始人
2024-05-26 00:14:06
0

一、简介

NioEventLoop的重要组成:Selector、线程、任务队列,他既会处理io事件,也会处理普通任务和定时任务.

1.下面是Selector,注意有两个哦后面会讲在这里插入图片描述
2.下面的爷爷类提供的Thread变量,其实下面发excutor用的就是这个一个线程。
任务队列就是thread上面的这个taskQueue变量
在这里插入图片描述
3.从曾祖父类中可以看到处理定时任务的任务队列
在这里插入图片描述

二、带着问题读源码

2.1selector在何时创建?

答案:在构造方法的openSelector()方法中被创建
在这里插入图片描述
在这里插入图片描述

2.2EventLoop为啥有两个Selector对象?

答案:为了在遍历SelectedKey时提升性能
继续往下看看openSelector方法:
在这里插入图片描述
SelectedSelectionKeySet的部分源码展现:
在这里插入图片描述
再看EventLoop构造方法就懂了:
1.selectorTuple 就是 new SelectorTuple(unwrappedSelector,new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet))
2.selectorTuple.selector就是new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet))
在这里插入图片描述
3.new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet))的底层可以看到,基本就是对unwrappedSelector进行了包装
在这里插入图片描述

2.3.EventLoop的Nio线程何时被启动?

答案:当首次调用execute方法时,通过state状态位控制线程只会启动一次

1.可以写一个测试代码,咱们追execute方法就行!

在这里插入图片描述
下面是其源码展示:
在这里插入图片描述

2.在inEventLoop的底层是通过thread变量和当前线程是否相等来判断是不是Nio线程

第一次执行时thread等于null,当然会返回false
在这里插入图片描述

3.随后通过addTask方法将任务提交到任务队列

在这里插入图片描述
在这里插入图片描述

4.第一次执行由于不属于nio线程,会执行startThread

在这里插入图片描述
在这里插入图片描述

2.4提交普通任务会不会结束select阻塞?

答案:会

1.重点追一下上面提及的run方法

在这里插入图片描述
发现netty的select底层是用了带超时时间的select方法
在这里插入图片描述

2.回到execute方法,分析后面的普通任务进来的执行逻辑

第二次execute方法进来,肯定是走下面这个wakeUp的逻辑
在这里插入图片描述
从底层可以看出wakeUp可以释放selector的select等待
在这里插入图片描述

2.5wakeup方法中的代码怎么理解? & wakenUp变量的作用是什么?

答案:只有其他线程提交任务时,才会调用上面2.4提到的selector.wakeup
wakenUp的作用:如果有多个其他线程都来提交任务,使用cas算法避免wakeUp被频繁调用

2.6每次循环时,什么时候会进入SelectStrategy.SELECT分支

答案:当没有任务时,才会进入SelectStrategy.SELECT分支,当有任务时,会调用selectNow方法,顺便拿到io事件
这得分析switch括号中方法的返回结果了,因为具体走哪个分支完全有这个case决定
在这里插入图片描述
由底层源码可知,档hasTasks()返回为fasle时,也就是没有任务才会走SELECT分支
在这里插入图片描述
如果有任务,则马上调用selector.selectNow把事件给拿到
在这里插入图片描述

2.7何时会select阻塞,阻塞多久?

答案:没有任务时阻塞一秒左右,只有三种情况才会跳出for的死循环:1.超时时间到了2.有任务3.有事件

在这里插入图片描述
在这里插入图片描述

2.8Nio空轮询bug在哪体现?如何解决?

答案:
1.bug的体现就是selector.select(timeout)方法可能没阻塞住,导致for循环一直空转(linux平台会产生)
2.解决办法是增加了selectCnt计数器,每次循环都会加1,默认达到512次就会认为bug产生,换一个新的selector,并会自动break
在这里插入图片描述
下面是for循环空转的终止条件,达到512次会重新创建一个新的selector,替换掉有问题的selector
在这里插入图片描述

2.9 ioRatio控制什么?设置为100有何作用?

答案:ioRatio控制处理io事件所占用的时间比例,如果设置100会让普通任务全部执行完(强烈不推荐!)。咱们可以看else的逻辑

由于Netty线程是单线程,如果处理普通任务的时间过长,势必会影响到io事件的处理
ioTime代表执行io事件处理耗费的时间
在这里插入图片描述

2.10selectedKeys优化是怎么回事?

答案:就是用数组类型的selectedKeys代替原来Set结构的SelectedKey,提升访问的效率

在上面2.2中提到了,selectedKeys是优化后数组类型的key集合,所以默认优化后会走if中的分支
在这里插入图片描述
继续追processSelectKeysOptimized方法,发现逻辑大致就是拿到nioChannel这个附件,执行其pipline中绑定的handler
在这里插入图片描述
processSelectedKey方法的底层是根据事件的类型做不同的处理
在这里插入图片描述

三、Netty中的Accept流程

原生nio中accept流程主要干了下面六件事情:
上面2.6-2.10已经分析到了前面三件事情,本段落时分析后续的三件事情在哪执行!
在这里插入图片描述

1.继续分析2.10中提到的unsafe.read(),这里会调到NioMessageUnsafe类中,我们关注doReadMessage这个方法即可

在这里插入图片描述
doReadMessages方法中可以看到nio原生的accept的过程,并主动创建了一个NioSocketChannel。而设置为非阻塞的过程在new NioSocketChannel方法中,有兴趣的朋友可以追一下
在这里插入图片描述

2.回到unsafe.read方法,往下继续看

这个pipeline.fireChannelRead就会调用到Netty源码解读-server端中2.3.3提到的acceptHandler
在这里插入图片描述
也就是会调用到ServerBootstrapAcceptor.channelRead,主要是设置一些参数,然后执行regitster方法
在这里插入图片描述
childGroup.register这个方法和Netty源码解读-server端中2.3.1的register的过程基本一致,也会切换成nio线程执行register0方法

在这里插入图片描述
在这里插入图片描述

继续分析pipeline.fireChannelActive,他势必也会执行head节点的active方法,又是熟悉的配方
在这里插入图片描述
又是在AbstractNioChannel.doBeginRead方法中关注到read事件
在这里插入图片描述

3.read事件触发

虽然该事件也会走2.10中提到的unsafe.read(),但和accept事件不同,他会进入NioByteUnsafe子类
会在doReadBytes方法中读取client端发送过来的数据,可以打断点看到经过这一行,byteBuf读指针发生了变化
在这里插入图片描述
后续的逻辑是通知其他的hander,链式执行…
在这里插入图片描述

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...