Netty

Netty 3源码分析(三)Bootstrap

Netty 3的启动类主要分为ServerBootstrap和ClientBootstrap,如下图

Bootstrap

Bootstrap类中本身的逻辑很少,但它维护了几个重要对象的引用

  • ChannelFactory:决定创建何种类型的Channel
  • Pipeline:默认使用的pipeline
  • PipelineFactory:创建新的Channel时,由该factory指定创搭配何种pipeline

ChannelFactory是预先构造的,并作为构造函数的参数传递给ServerBootstrap

PipelineFactory也需要自己指定,以此设定自己的Handler

ServerBootstrap

对于Server端,随后执行bind()方法,再转入内部的bindAsync()启动服务

  1. 创建了Binder,它是一个UpstreamHandler
  2. parentHandler通常没有设置,为null
  3. 创建了bossPipeline,来自Channels.pipeline(),一个DefaultChannelPipeline实例,向其中添加了binder
  4. 通过ChannelFactory创建了Channel,这里对应的是NioServerSocketChannel,绑定了bossPipeline
  5. 创建一个ChannelFuture作为返回值
  6. 为binder添加listener,用于接收启动状态结果

NioServerSocketChannelFactory

初始化的时候会创建几个重要的对象

  1. bossExecutor与workerExecutor,默认为Executors.newCachedThreadPool()
  2. 指定默认的boss数为1,worker数为cpu核数 * 2
  3. 创建NioServerBossPool和NioWorkerPool
  4. 启动boos线程和worker线程
  5. 指定boss来自bossPool.nextBoss()
  6. 指定sinki为NioServerSocketPipelineSink

NioServerSocketChannel

启动工作传递到了NioServerSocketChannelFactory的newChannel()方法,将创建一个NioServerSocketChannel

  1. factory和pipeline已通过ServerBootstrap创建完成
  2. sink、boss、workerPool由factory初始化时创建,所有channel将共享这些资源
  3. 创建了jdk中的ServerSocketChannel,blocking设置为false
  4. 执行fireChannelOpen(this)进行事件通知

创建了UpstreamChannelStateEvent,这个事件将流转至作为UpstreamHandler的Binder,并根据事件配型调用channelOpen方法

channel.bind()随后转入Channels.bind()

发送了一个Downstream的BOUND事件,由于没有配置DownstreamHandler,这个事件将直接进入pipeliine末端的sink,即NioServerSocketPipelineSink

BOUND事件会调用boss的bind()方法

这里将创建一个RegisterTask(实现了Runnable接口),并把它加入到boss线程的任务队列中等待执行

在汇集了所有信息后,这里会真正执行ServerSocket的bind操作,以及向selector注册OP_ACCEPT事件,同时再次发送了一个Upstream的BOUND事件,由于没有注册对应的handler,这个事件将不被处理。至此Server端的启动工作就全部结束了。

ClientBootstrap

Client端的启动和Server非常类似,只是创建的对象和发送的事件会有不同,我们可以按照相同的逻辑梳理一下

  1. 调用connect()方法
  2. 创建一个DefaultChannelPipeline,不添加Handler
  3. 通过ChannelFactory创建channel

NioClientSocketChannelFactory

  1. 指定默认的boss数为1,worker数为cpu核数 * 2
  2. 创建NioClientBossPool和NioWorkerPool
  3. 启动clientBoss线程和worker线程
  4. 指定sink为NioClientSocketPipelineSink

NioClientSocketChannel

  1. factory、pipeline、sink已确定
  2. 不需要boss,指定一个worker来自workerPool.nextWorker(),
  3. 创建一个jdk的SocketChannel
  4. 发送一个Upstream的Open事件

初始化工作之后,ClientBootstrap调用channel.connect()方法,转入Channels.connect(),发送一个Downstream的CONNECTED事件,它将由NioClientSocketPipelineSink进行处理。

这里可以看到jdk中SocketChannel的connect方法,连接被真正建立,Client的主要启动流程结束。在selector上注册读写事件相关的工作,是在Worker线程中完成的,这部分将在后面的文章中进行介绍。

 

© 2015, 高飞航.cn. 版权所有.

About gaofeihang

开发工程师,本站的作者。欢迎留下您宝贵的意见!

发表评论

电子邮件地址不会被公开。 必填项已用*标注