东山明月

V1

2022/04/21阅读:36主题:蓝莹

2-3. 注册selector

首先回顾一下之前做的工作,在netty服务端启动中,详细说明了netty初始化过程的四个步骤:

  • 创建服务端channel,调用jdk底层的api创建jdk的channel,之后netty将其包装成自己的channel,并创建一些基本组件绑定到该channel上。
  • 初始化服务端channel,创建完成之后会对channel做一些初始化的工作,比如初始化一些基本属性,添加一些逻辑处理器。
  • 注册selector,netty将jdk底层的channel注册到事件轮询器selector上面。
  • 端口绑定,调用jdk底层api实现对端口的监听。

其中的前两步在创建服务端channel初始化服务端channel中详细介绍,而本小节该则介绍第三步:注册selector,其主要作用是将jdk底层的channel注册到事件轮询器上。

1. 注册selector总体流程

同样先根据闪电侠给出的整体流程,对注册selector部分有一个整体的认知:

源码部分接着channel的注册与初始化部分,如下图可知,在初始化完成之后有一个注册的部分,此处的代码对应于AbstractChannel类中的register方法,即总体流程中的第一步入口。

2. register(channel)方法

该方法的源码如下:

其中前面几行是if判断,主要的地方有两个:AbstractChannel.this.eventLoop = eventLoop负责将绑定eventLoop线程用于处理只有的请求;register0(promise)则是实际注册的部分,其源码如下:

register0方法主要分析图中标出来的三个地方。

2.1 doRegister()方法

该方法位于AbstractNioChannel类中,其源码如下:

其中javaChannel()方法返回之前通过jdk底层api创建的服务端channel,之后的register部分则是具体的注册,将this注册到eventLoop().selector上面,这里的this是一个AbstractNioChannel对象,我理解是对java底层channel的一个封装。还有一个参数是ops表示注册是关心的时间,0表示不关心任何事件。这样netty通过调用java底层channel的注册方法完成selector的注册。

2.2 invokeHandlerAddedIfNeeded()与fireChannelRegistered()

在register0()方法中,我们讲主要关心三个步骤,除了doRegister之外便是本小节需要展开的部分。

其中2和3部分对应于用户代码的handler部分,这里我们传入了一个ServerHandler,其重写了三个方法,这三个方法在便是与invokeHandlerAddedIfNeeded()、fireChannelRegistered()对应。

将程序运行起来,变可以看到我们在ServerHandler中输出的内容:

3. 小结

  • 注册selector时,以register(channel)方法为入口
    • 首先绑定线程
    • 之后由regiter0完成实际的注册,而注册部分又主要分三步
      • 调用jdk底层channel的注册方法完成selector的注册
      • invokeHandlerAddedIfNeeded()
      • fireChannelRegistered()

分类:

后端

标签:

Java

作者介绍

东山明月
V1