Netty架构 - NioServerSocketChannel

前言

在解析Netty中的Channel如何应用之前,首先看下如下的代码:
Netty架构 - NioServerSocketChannel

这段代码,一些使用过netty的朋友们,都蛮了解的。
接下来从server.channel(NioServerSocketChannel.class)这行代码开始本篇文章的解析旅程。

服务端Channel的实例化

概述
设置非阻塞模式,建立NioServerSocketChannel与ServerSocket的关联关系,然后通过ReflectiveChannelFactory完成NioServerSocketChannel的实例化。
Netty架构 - NioServerSocketChannel

首先看下外层的channelFactory(…)方法做了什么事。
Netty架构 - NioServerSocketChannel
Netty架构 - NioServerSocketChannel

很显然是设置ChannelFactory属性为一个ReflectiveChannelFactory实例。

然后看下ReflectiveChannelFactory实例如何构造的。
Netty架构 - NioServerSocketChannel
Netty架构 - NioServerSocketChannel

由前文可知,方法的参数,我们传递的是NioServerSocketChannel.class。这里利用反射调用它的无参构造器进行实例化。

Netty架构 - NioServerSocketChannel

先看下newSocket(…)方法的处理逻辑。
Netty架构 - NioServerSocketChannel

这里的SelectorProvider,通过在ide工具中debug,我们可以知道实际上是KQueueSelectorProvider。(由SelectorProvider.provider()方法生成)

Netty架构 - NioServerSocketChannel

可以看出得到的是ServerSocketChannelImpl这个实例,并且将KQueueSelectorProvider作为参数传入。

回到它的构造器方法。
Netty架构 - NioServerSocketChannel

  • javaChannel():实际上是我们前面看到的ServerSocketChannelImpl
  • socket():构造一个ServerSocket实例。

由此,NioServerSocketChannelConfigNioServerSocketChannelServerSocket与之关联。如同它的名字一样,存储相关的配置。

接着看调用其父类的构造器做了什么事。
Netty架构 - NioServerSocketChannel

ch.configureBlocking(false)这行代码,可以看出设置非阻塞模式。

接着往下看。
Netty架构 - NioServerSocketChannel

对parent、id、unsafe、pipeline属性进行赋值。

AbstractBootstrap#initAndRegister()方法有这样一行代码。
Netty架构 - NioServerSocketChannel

由此,由ReflectiveChannelFactory完成NioServerSocketChannel的实例化。

服务端Channel的初始化

这部分从前言例子的server.bind(port)这行代码开始分析。

概述
将ServerBoostrap#option(…)、attr(…)等方法设置的属性传递给NioServerSocketChannel。然后在DefaultChannelPipeline中添加ServerBootstrap#handler(…)方法定义的ChannelHandler以及ServerBootstrapAcceptor。

bind(…)方法会走到doBind(…)方法,如下:
Netty架构 - NioServerSocketChannel

重点关注下initAndRegister()方法。(剩余的方法内容会在注册中接着分析)
Netty架构 - NioServerSocketChannel

  • channelFactory:ReflectiveChannelFactory类型。

Netty架构 - NioServerSocketChannel

在ServerBootstrap#option(…)方法设置的参数传递给NioServerSocketChannelConfig,也就是NioServerSocketChannel的属性。
在ServerBootstrap#attr(AttributeKey, Object)方法设置的key、value传递给NioServerSocketChannel。

接着看init(…)方法。
Netty架构 - NioServerSocketChannel

在ServerBootstrap#childGroup(…)、childHandler(…)、childOption(…)以及childAttr(…)方法设置的参数传递给ServerBootstrapAcceptor。

Netty架构 - NioServerSocketChannel

在DefaultChannelPipeline中,添加了一个ChannelInitializer。其在initChannel(…)方法,定义了在DefaultChannelPipeline中添加ServerBootstrap#handler(…)方法定义的ChannelHandler、以及ServerBootstrapAcceptor实例。

ChannelInitializer,一个特定的ChannelInboundHandler,提供了便捷的方法(也就是initChannel(…)方法)用于初始化一个Channel。
ServerBootstrapAcceptor,同样是一个ChannelInboundHandler。其封装了如下属性:
Netty架构 - NioServerSocketChannel

服务端Channel的注册

概述
核心是调用nio原生的ServerSocketChannelImpl#register(Selector sel, int ops, Object att)方法,将Netty的NioServerSocketChannel作为attr参数进行传入,从而与nio原生的ServerSocketChannelImpl建立关联性,最后完成Channel在Selector上的注册。

接着AbstractBootstrap#initAndRegister()方法,展开分析,有如下一行代码:
Netty架构 - NioServerSocketChannel

  • group():ServerBootstrap#group(…)方法指定的NioEventLoopGroup。

Netty架构 - NioServerSocketChannel

首先看下next()方法,如下:
Netty架构 - NioServerSocketChannel

这里是调用父类的next()方法,然后进行类型转换。EventLoop是一个ScheduledExecutorService。

Netty架构 - NioServerSocketChannel

  • chooser:PowerOfTwoEventExecutorChooser类型。

Netty架构 - NioServerSocketChannel

  • executors:实际上是NioEventLoop数组。

现在,回过头看下register(…)的处理逻辑。

Netty架构 - NioServerSocketChannel

  • channel:NioServerSocketChannel。
  • this:指代NioEventLoop。

Netty架构 - NioServerSocketChannel

从register(…)方法中,挑选了如下代码,也就是注册Channel的核心代码。
Netty架构 - NioServerSocketChannel

接着跟进代码(有省略)。
Netty架构 - NioServerSocketChannel

  • javaChannel():nio原生的ServerSocketChannelImpl。
  • unwrappedSelector:KQueueSelectorImpl。
  • this:指代NioServerSocketChannel。

可以看出实质上是nio原生方法 - register(Selector sel, int ops, Object att)。将ServerSocketChannelImpl注册到Selector上,同时将Netty的NioServerSocketChannel与之关联。

深入nio的AbstractSelectableChannel#register(…)方法,一看究竟。
Netty架构 - NioServerSocketChannel

不难看出找到Selector关联的SelectionKey,然后通过SelectionKey#attach(…)方法将NioServerSocketChannel传入,从而建立关联性。