Netty之Channel、NioEventLoopGroup、客户端connect方法总结

一、bind方法

详情请见以前的文章:Netty之Channel、NioEventLoopGroup、客户端connect方法总结

bind方法会调用initAndRegister方法

 1.1 initAndRegister方法

1.1.1 生成channel的构造方法

  1.  channel.newChannel()。通过反射生成了我们显式设置的NioSocketChannel.class对象,反射是用它的无参构造方法生成的。
  2. 无参构造方法级联调用了多个构造参数。在这个过程中,通过jdk自带的spi机制生成了原生nio的socketChannel对象,这个参数最终会在AbstractChannel的构造方法中设置到ch属性中,并且ch会设置成不阻塞
  3. 生成id,unsafe,pipeline等属性并赋值

 1.1.2 init方法

  1. 将显示设置的handler配置到pipeline中
  2. 将显示配置的option设置到channel的pipeline中
  3. 将显示配置attr配置到channel中

1.1.3 register方法

这个方法在MultithreadEventLoopGroup类中。

  1. 选择一个EventLoop,调用其register方法
  2. 最终调用jdk原生nio的Channel.register(selector)

问题:服务端selector是在哪里生成的?  

1.1.4 注册触发事件 

  1. 调用ChannelInitializer.channelRegister()
  2. 内部调用了钩子方法initChannel(),这个就是我们自己写的initChannel()

二、new NioEventLoopGroup()

 详情请见以前的文章:揭开BootStrap的神秘面纱

  1.  构造方法最终调用MultithreadEventExecutorGroup;
    线程数nThreads如果没传,则设置为cpuNum*2;
    children:他其实相当于线程池,存放EventLoop,类型为EventExecutor[]类型,数组大小就为nThreads;
  2. 创建nThreads个EventLoop,放到children这个数组中
  3. 来看NioEventLoop构造方法:
    ①创建selector,selector是NioEventLoop的属性。
    ②将其他的值放到属性中,例如Executor等

上面的问题就得到解答了:

在 NioEventLoop构造方法的时候创建了selector

三、客户端发起请求

最终调用原生的channel.connect方法。

不解的地方:

不懂为什么要递归调用pipeline(TailContext、HeadContext)的connect方法?

四、ServerBootstrap

详情请见以前的文章:揭秘ServerBootstrap神秘面纱(服务端ServerBootstrap)

  1. NioServerSocketChannel的创建、服务端Channel(NioServerSocketChannel)的初始化、ChannelPipeline初始化、服务端注册到Selector与客户端过程大致相同
  2. 服务端有两个EventLoopGroup对象;
    boossGroup-连接事件;workerGroup-io事件
  3. bossGroup不断监听客户端连接,当有新连接时,bossGroup就会为此连接初始化各项资源。然后从workerGroup中选中一个EventLoop绑定此连接,接下来的交互就全在此EventLoop中了
  4. 在启动时——bind()方法,用到的group为bossGroup
  5. workerGroup在哪与NioSocketChannel关联呢?——下面给出答案

问题:workerGroup在哪与NioSocketChannel关联呢?

ServerBootstrap中有channelRead方法,里面有childGroup.register(child)——child就是Channel。

  1. 在服务端调用ServerBootstrap.doBind方法时,会调用init()方法,ServerBootstrap重写了init()方法。
  2. 在这个重写的init方法里,为channel的pipeline添加了新的handler——ServerBootstrapAcceptor(ServerBootstrap的内部类)
  3. ServerBootstrapAcceptor的channelRead方法,在接收到连接事件就会触发,它包含了这段代码:
    childGroup.register(child)...
  4. 上述代码中childGroup就是workerGroup

 4.1 handler

服务端有两个group:bossGroup和workerGroup。

猜想:bossGroup关心连接事件,workerGroup关心io事件。

关于这个猜想以后再验证

4.2 selector事件轮询

  1. doBind方法——>channel.eventLoop().excute()-SingleThreadEventExecutor.startThread()——>SingleThreadEventExecutor.this.run()
  2. 在上述run方法里,是一个死循环:轮询+事件+唤醒/休眠
  3. 原生nio的selector会有空轮询bug,它的selector.select()方法有问题,不该唤醒的时候有可能会一直唤醒
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值