Netty源码分析第1章(Netty启动流程)—->第1节: 服务端初始化

释放双眼,带上耳机,听听看~!

Netty源码分析第一章:  Server启动流程

 

概述:

        本章主要讲解server启动的关键步骤, 读者只需要了解server启动的大概逻辑, 知道关键的步骤在哪个类执行即可, 并不需要了解每一步的运作机制, 之后会对每个模块进行深度分析

 

第一节:服务端初始化

 

首先看下在我们用户代码中netty的使用最简单的一个demo:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1//创建boss和worker线程(1)
2EventLoopGroup bossGroup = new NioEventLoopGroup(1);
3EventLoopGroup workerGroup = new NioEventLoopGroup();
4//创建ServerBootstrap(2)
5ServerBootstrap b = new ServerBootstrap();
6//初始化boss和work线程化两个线程(3)
7b.group(bossGroup, workerGroup)
8        //声明NioServerSocketChannel(4)
9        .channel(NioServerSocketChannel.class)
10        //初始化客户端Handler(5)
11        .childHandler(new ChannelInitializer<SocketChannel>() {
12            @Override
13            public void initChannel(SocketChannel ch) {
14                ch.pipeline().addLast(new StringDecoder());
15                ch.pipeline().addLast(new StringEncoder());
16                ch.pipeline().addLast(new ServerHandler());
17            }
18        });
19//绑定端口(6)
20ChannelFuture f = b.bind(8888).sync();
21f.channel().closeFuture().sync();
22

 

相信这段代码使用过
netty
的同学应该都不陌生
.
这里每一步都用了注释和步骤序号进行标注
,
为了方便学习过程中更容易的定位
.
每一步的讲解
,
尽量自己也去跟到源码中
,
这样会有个更深刻的理解

第一步
,
创建两个线程组:

其中会调用
NioEventLoopGroup()的构造方法
, 其中的创建逻辑
, 并不是这章的重点
, 在这里大家只需要知道这里创建了两个线程组

第二步
, 创建
ServerBootstrap, 我们发现
, 这里创建只调用了其无参的构造方法
, 原因很简单
, 就是参数太多
, 尽量要用构造方法去初始化
, 而是使用后面的
build的方式

第三步
, 初始化
boss和
work线程化两个线程

 

我们跟到
group方法中去看:

1
2
3
4
5
6
7
1public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
2    //设置线程池组
3    super.group(parentGroup);
4    this.childGroup = childGroup;
5    return this;
6}
7

为了代码可读性
, 去掉非关键代码
(以后不再赘述
), 我们看到这里初始化了自家的属性
childGroup, 而这个属性就是我们传入的
worker线程组
, 而
boss线程组则交给了其父类的
group方法去做处理

 

我们点进去
super.group(parentGroup), 进入到
ServerBootstroop的父类
AbstractBootstrap的
group()方法:

1
2
3
4
5
1public B group(EventLoopGroup group) {
2    this.group = group;
3    return (B) this;
4}
5

看到在其父类初始化了
boss线程

我们看到这个方法返回了
this, 也就是
ServerBootstroop自身
, 这样通过自身对象不断的
build进行属性初始化
, 之后的方法也是如此

至此
, worker和
boss两个线程组初始化完毕

 

回到最开始的第四步
, 再点进到
channel(ServerSocketChannel.class)方法当中
, 我们看到
AbsractServerBootstrap的
channel(Class<? extends C> channelClass)方法:

1
2
3
4
1public B channel(Class&lt;? extends C&gt; channelClass) {
2    return channelFactory(new ReflectiveChannelFactory&lt;C&gt;(channelClass));
3}
4

我们看到这个这返回的是
channelFactory(new ReflectiveChannelFactory<C>(channelClass))方法
, 并且传入一个
ReflectiveChannelFactory对象的实例
,

我们可以跟进去看下
ReflectiveChannelFactory的构造方法:

1
2
3
4
1public ReflectiveChannelFactory(Class&lt;? extends T&gt; clazz) {
2    this.clazz = clazz;
3}
4

这里初始化了一个成员变量
clazz, 而这个
clazz就是用户代码调用
channel(NioServerSocketChannel.class)传入的
NioServerSocketChannel的
class对象

 

回到
channelFactory(new ReflectiveChannelFactory<C>(channelClass))方法
, 点进去
, 我们看到
:

1
2
3
4
1public B channelFactory(io.netty.channel.ChannelFactory&lt;? extends C&gt; channelFactory) {
2    return channelFactory((ChannelFactory&lt;C&gt;) channelFactory);
3}
4

继续跟
:

1
2
3
4
1public B channelFactory(io.netty.channel.ChannelFactory&lt;? extends C&gt; channelFactory) {
2    return channelFactory((ChannelFactory&lt;C&gt;) channelFactory);
3}
4

跟到最后
:

1
2
3
4
5
1public B channelFactory(ChannelFactory&lt;? extends C&gt; channelFactory) {
2    this.channelFactory = channelFactory;
3    return (B) this;
4}
5

这里初始化了
channelFactory, 而这个
channelFactory就是刚才创建的
ReflectiveChannelFactory对象
, 这里我们记住这个对象中初始化了我们的
NioServerSocket的
class对象

至此
, 我们的
ServerSocketChannel的
class对象初始化完成

 

我们跟到最开始的第五步, 初始化客户端
Handler:

1
2
3
4
5
6
7
8
9
1.childHandler(new ChannelInitializer&lt;SocketChannel&gt;() {
2            @Override
3            public void initChannel(SocketChannel ch) {
4                ch.pipeline().addLast(new StringDecoder());
5                ch.pipeline().addLast(new StringEncoder());
6                ch.pipeline().addLast(new ServerHandler());
7            }
8        });
9

childHandler()
方法比看起来比较复杂
, 其实不难理解
, 就是传入
ChannelInitializer类子类的一个对象
(有关匿名内部类不知道的同学可以找下相关资料学习下
), 也就是一个
Handler, 这个
Handler是做什么的
, 目前不需要关心
, 以后会讲到
, 这里我们只需知道这个方法传入一个
handler对象

 

我们点进
childHandler这个方法
:

1
2
3
4
5
1public ServerBootstrap childHandler(ChannelHandler childHandler) {
2    this.childHandler = childHandler;
3    return this;
4}
5

发现同样非常简单的初始化了
handler属性

这一小节至此结束
, 只是初始化了
ServerBootstrap的各个属性
, 是不是非常简单

 

我们可以看到
, 通过对象
build的方式
, 可以初始化非常多的属性
, 并且代码要比构造方法的方式可读性要好的多
, 同学们可以将这种思想用在自己的代码当中

 

上一节: 前言, 概述及目录

下一节: NioServerSocketChannel的创建

 

给TA打赏
共{{data.count}}人
人已打赏
安全技术

基于Node.js的自动化构建工具Grunt.js

2021-12-21 16:36:11

安全技术

从零搭建自己的SpringBoot后台框架(二十三)

2022-1-12 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索