Netty接受新连接的流程

Netty在启动之后,io.netty.channel.nio.NioEventLoop#run就会一直轮询,判断当前是否有可以执行的事件,也就是调用selector.select选择selector注册到channel时selector感兴趣的事件,这里select不会直接用jdk的select,而是调用netty自己实现的io.netty.channel.nio.SelectedSelectionKeySetSelector#select(),这里用了1个集合缓存之前select的key,如果再次select时,会清除之前缓存的key

io.netty.channel.nio.SelectedSelectionKeySetSelector#select()

KQueueSelectorImpl在select的时候,会往selectionKeys里添加选好的key,我们在SelectedSelectionKeySet的add里打个断点,会发现调用到这个add方法,那netty是什么时候将KQueueSelectorImpl里的Set替换成netty的实现,netty的实现又有什么较好的地方呢,这个我们后面再说

io.netty.channel.nio.SelectedSelectionKeySetSelector#select()

selectKey选择出来之后,就要执行处理操作了,这里处理分为两种,一种是优化过的,一种是没有优化过的

io.netty.channel.nio.NioEventLoop#processSelectedKeys

我们查看下io.netty.channel.nio.NioEventLoop#processSelectedKeysOptimized的实现,会发现调用到io.netty.channel.nio.NioEventLoop#processSelectedKey,而这个方法针对OP_ACCEPT、OP_READ操作,会调用unsafe去执行read操作,在unsafe(NioMessageUnsafe)的read操作里,会调用io.netty.channel.socket.nio.NioServerSocketChannel#doReadMessages方法读取数据,如下文所示,我们可以看到这里会创建一个NioSocketChannel,作为和客户端传递消息的通道

io.netty.channel.socket.nio.NioServerSocketChannel#doReadMessages

获取到新的NioSocketChannel之后,就要调用io.netty.bootstrap.ServerBootstrap.ServerBootstrapAcceptor#channelRead会添加handler,设置options,attrs参数,并将新创建的channel注册到childGroup上

io.netty.bootstrap.ServerBootstrap.ServerBootstrapAcceptor#channelRead

上面注册操作会调用下面这个方法,next会获取一个NioEventLoop,这里获取方式有两种,分别是io.netty.util.concurrent.DefaultEventExecutorChooserFactory.GenericEventExecutorChooser#next和io.netty.util.concurrent.DefaultEventExecutorChooserFactory.PowerOfTwoEventExecutorChooser#next,分别是用取余和位与运算计算的,第二种方式更高效一点

然后register会调用到unsafe.register,这里和启动时流程类似,会调用这个channel注册selector,并将感兴趣的事件设置为0,然后调用pipeline.invokeHandlerAddedIfNeeded、pipeline.fireChannelRegistered回调实现的方法

和启动的流程类似,head调用unsafe.read的时候,会先给这个channel注册感兴趣的事件,这里如果selector还没对OP_READ事件感兴趣,会注册上OP_READ(触发Active的时候)

到这里processSelectedKeys流程就执行完了,后面会执行提交的任务,后面再说

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。