【Netty】6 ---源码ServerBootstrap

之前写了两篇与Bootstrap相关的文章,一篇是ServerBootstrap的父类,一篇是客户端Bootstrap类,博客地址:

【Netty】源码AbstractBootstrap

【Netty】源码 Bootstrap

所以接下来 有关ServerBootstrap 源码的分析,如果上面已经分析过了,就不再陈述。

一、概念

ServerBootstrap可以理解为服务器启动的工厂类,我们可以通过它来完成服务器端的 Netty 初始化。

作用职责:EventLoop初始化,channel的注册过程 ,关于pipeline的初始化,handler的添加过程,服务端连接分析。

下面也先看下源码

​      // 定义一对线程组
​ // 主线程组, 用于接受客户端的连接,但是不做任何处理,跟老板一样,不做事
​ EventLoopGroup bossGroup = new NioEventLoopGroup();
​ // 从线程组, 老板线程组会把任务丢给他,让手下线程组去做任务
​ EventLoopGroup workerGroup = new NioEventLoopGroup(); try {
// netty服务器的创建, 辅助工具类,用于服务器通道的一系列配置
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup) //绑定两个线程组
.channel(NioServerSocketChannel.class) //指定NIO的模式
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new HelloServerInitializer()); // 子处理器,用于处理workerGroup // 启动server,并且设置8088为启动的端口号,同时启动方式为同步
ChannelFuture channelFuture = serverBootstrap.bind(8088).sync(); // 监听关闭的channel,设置位同步方式
channelFuture.channel().closeFuture().sync();
} finally {
//退出线程组
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}

二、源码解析

1、group(bossGroup, workerGroup)

这里跟客户端明显的一个区别就是,客户端只传入了一个NioEventLoopGroup,而服务端传入了两个。

 /**
* 这里调用的是 ServerBootstrap 类本身的 group 方法 发现传入的两个EventLoopGroup
* 一个赋值给父类(AbstractBootstrap),另一个赋值给 该对象本身属性
*/
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) { //调用父类的group方法
super.group(parentGroup);
if (childGroup == null) {
throw new NullPointerException("childGroup");
}
if (this.childGroup != null) {
throw new IllegalStateException("childGroup set already");
}
this.childGroup = childGroup;
return this;
}

而在服务器端的初始化时, 我们设置一个是 bossGroup, 另一个是 workerGroup. 那么这两个 EventLoopGroup 到底是怎么分工的?

bossGroup 是用于服务端 的 accept 的, 即用于处理客户端的连接请求.workerGroup 它们负责客户端连接通道的 IO 操作。

关于 bossGroup 与 workerGroup 的关系, 我们可以用如下图来展示(盗图):

首先, 服务器端 bossGroup 不断地监听是否有客户端的连接, 当发现有一个新的客户端连接到来时, bossGroup 就会为此连接初始化各项资源,然后从 workerGroup 中选出一个 EventLoop 绑定到此客户端连接中. 那么接下来的服务器与客户端的交互过程就全部在此分配的 EventLoop 中了。至于 bossGroup 和 workerGroup 和 channel 如何联系到一起的,等下面再讲bind(host)方法的时候在用源码展示,因为是通过bind(host)开始将他们联系到一起的。

2、channel(NioServerSocketChannel.class)方法

这里和上一篇说的channl是差不多的,具体源码可以看上一篇就可以了,只是这里传入的类是NioServerSocketChannel,而客户端是NioSocketChannel,但他们都是通过类的反射

机制获得类的对象的。同样真正用到该对象的时候,也是在bind(host)方法里。

有关NioServerSocketChannel对象和之前的NioSocketChannel对象本身是没有讲过的。

3、handler()和childHandler()

我们跟客户端比较发现还是有明显区别的, 和 EventLoopGroup 一样, 服务器端的 handler 也有两个, 一个是通过 handler() 方法设置 handler 字段, 另一个是通过

childHandler() 设置 childHandler 字段。不过handler()方法并不是必须的,而childHandler()方法是必须调用的。

看代码

    /**handler(new LoggingHandler(LogLevel.INFO))
*
* 我们发现channel方法调用的是父类(AbstractBootstrap)的方法
* 所以这个 handler 字段与 accept 过程有关, 即这个 handler 负责处理客户端的连接请求
*/
public B handler(ChannelHandler handler) {
if (handler == null) {
throw new NullPointerException("handler");
}
this.handler = handler;
return self();
} /** 再看childHandler(class)
*
*很明显 这个childHandler 方法是属于ServerBootstrap 本身的方法
* 所以推测: 这个childHandler 就是负责和客户端的连接的 IO 交互
*/
public ServerBootstrap childHandler(ChannelHandler childHandler) {
if (childHandler == null) {
throw new NullPointerException("childHandler");
}
this.childHandler = childHandler;
return this;
}

有关handler和childHandler在哪个地方会被运用,等下将bind()方法的时候,我们在看他的源码。

4、bind(host)方法

bind(host)才是整个流程的关键,前面做得只是初始化了一些netty客户端运行的对象(可以理解成只是创建了对象,并没有使用它),但真正用到这些这些对象,

还是在bind(host)方法里。我们一步一步跟着源码走,里面会省略一些不重要的代码

        /**
* 1、调用父类(AbstractBootstrap)的方法
* <p>
* 作用: 根据端口号 创建一个InetSocketAddress对象,用于连接连接服务器
*/
public ChannelFuture bind(int inetPort) {
return bind(new InetSocketAddress(inetPort));
} /**
* 2、继续调用父类(AbstractBootstrap)的方法
* <p>
* 作用: 做一些校验工作
*/
public ChannelFuture bind(SocketAddress localAddress) {
validate();
if (localAddress == null) {
throw new NullPointerException("localAddress");
}
return doBind(localAddress);
} /**
* 3、继续调用父类(AbstractBootstrap)的方法
* <p>
* 作用: 这个方法做了很多事情
*/
private ChannelFuture doBind(final SocketAddress localAddress) {
//3、1 具体看下面3、1的代码部分
final ChannelFuture regFuture = initAndRegister();
final Channel channel = regFuture.channel(); ChannelPromise promise = channel.newPromise();
doBind0(regFuture, channel, localAddress, promise);
return promise;
}
} /**
* 3、1 这步做了很多重要的事情
*/
final ChannelFuture initAndRegister() {
Channel channel = null; //这里终于调用newChannel方法了,这里就是之前BootStrap讲的ReflectiveChannelFactory对象的方法,这里的
//channel 对象是NioServerSocketChannel。
channel = channelFactory.newChannel();
//这个方法也太重要了 和handle有关 下面3.1.1 讲它
init(channel); //这里的group()获取的就是bootstrap ,这里面会调用next方法 来循环获取下一个channel 具体的我就不点进去分析了
//这里group().register(channel) 将 bossGroup 和 NioServerSocketChannel 关联起来了.
ChannelFuture regFuture = config().group().register(channel); return regFuture;
} /**
* 3.1.1 首先可以看到into的方法在父类(AbstractBootstrap)已经提供,只是子类写具体实现代码
*/
abstract void init(Channel channel) throws Exception; /**
* 我们再来看ServerBootstrap实现了init方法,这里面做了很多事
* 比如workerGroup相关,还有handel相关
*/
@Override
void init(Channel channel) throws Exception { //通过channel获得ChannelPipeline,说明每一个channel都会对应一个ChannelPipeline
ChannelPipeline p = channel.pipeline(); //这里终于获得workerGroup 对象
final EventLoopGroup currentChildGroup = childGroup;
//这里获得childHandler对象
final ChannelHandler currentChildHandler = childHandler;
final Entry<ChannelOption<?>, Object>[] currentChildOptions;
final Entry<AttributeKey<?>, Object>[] currentChildAttrs; p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(final Channel ch) throws Exception {
final ChannelPipeline pipeline = ch.pipeline();
//获得handel方法传入的对象
ChannelHandler handler = config.handler(); //这一步说明 .handler(new LoggingHandler(LogLevel.INFO))方法不是必须要的
//如果你没有调handler方法也没有关系 ,因为它会在这路做一层判断
if (handler != null) {
pipeline.addLast(handler);
} //到这里线程就开始启动运行了 发现已经讲Channel,ChannelPipeline,workerGroup,childHandler等全部联系到了一起。
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
}

源码博客推荐

有些源码自己也没有去分析 比如:NioServerSocketChannel对象本身,ChannelPipeline对象。

下面推荐源码专题博客

1、Netty源码分析教程

2、Netty学习笔记

如果一个人充满快乐,正面的思想,那么好的人事物就会和他共鸣,而且被他吸引过来。同样,一个人老带悲伤,倒霉的事情也会跟过来。

                                                  ——在自己心情低落的时候,告诫自己不要把负能量带给别人。(大校14)

【Netty】(6) ---源码ServerBootstrap的更多相关文章

  1. Netty 4源码解析:请求处理

    Netty 4源码解析:请求处理 通过之前<Netty 4源码解析:服务端启动>的分析,我们知道在最前端"扛压力"的是NioEventLoop.run()方法.我们指定 ...

  2. Netty 4源码解析:服务端启动

    Netty 4源码解析:服务端启动 1.基础知识 1.1 Netty 4示例 因为Netty 5还处于测试版,所以选择了目前比较稳定的Netty 4作为学习对象.而且5.0的变化也不像4.0这么大,好 ...

  3. netty : NioEventLoopGroup 源码分析

    NioEventLoopGroup 源码分析 1. 在阅读源码时做了一定的注释,并且做了一些测试分析源码内的执行流程,由于博客篇幅有限.为了方便 IDE 查看.跟踪.调试 代码,所以在 github ...

  4. Netty(6)源码-服务端与客户端创建

    原生的NIO类图使用有诸多不便,Netty向用户屏蔽了细节,在与用户交界处做了封装. 一.服务端创建时序图 步骤一:创建ServerBootstrap实例 ServerBootstrap是Netty服 ...

  5. 我为 Netty 贡献源码 | 且看 Netty 如何应对 TCP 连接的正常关闭,异常关闭,半关闭场景

    欢迎关注公众号:bin的技术小屋,本文图片加载不出来的话可查看公众号原文 本系列Netty源码解析文章基于 4.1.56.Final版本 写在前面..... 本文是笔者肉眼盯 Bug 系列的第三弹,前 ...

  6. Netty(7)源码-ByteBuf

    一.ByteBuf工作原理 1. ByteBuf是ByteBuffer的升级版: jdk中常用的是ByteBuffer,从功能角度上,ByteBuffer可以完全满足需要,但是有以下缺点: ByteB ...

  7. netty下载源码并导入idea

    netty源码导入eclipse会有一些兼容性问题,网上有解决方案,官方推荐idea,故此用idea. 拷贝git地址:https://github.com/netty/netty.git 使用git ...

  8. Netty ByteBuf源码分析

    Netty的ByteBuf是JDK中ByteBuffer的升级版,提供了NIO buffer和byte数组的抽象视图. ByteBuf的主要类集成关系: (图片来自Netty权威指南,图中有一个画错的 ...

  9. 【Netty】源码分析目录

    前言 为方便系统的学习Netty,特整理文章目录如下. [Netty]第一个Netty应用 [Netty]Netty核心组件介绍 [Netty]Netty传输 [Netty]Netty之ByteBuf ...

随机推荐

  1. redis基础操作~~数据备份与恢复、数据安全、性能测试、客户端连接、分区

    数据备份与恢复 数据备份redis save 命令用于创建当前数据库的备份. redis 127.0.0.1:6379> SAVE OK 该命令将在 redis 安装目录中创建dump.rdb文 ...

  2. 【环套树+树形dp】Bzoj1040 [ZJOI2008] 骑士

    Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火 ...

  3. bzoj 3759 Hungergame 博弈论+线性基

    和nim游戏类似 易证必败状态为:当前打开的箱子中石子异或和为0,没打开的箱子中不存在一个子集满足异或和为0 因为先手无论是取石子还是开箱子,后手都可以通过取石子来使状态变回原状态 所以只需判定是否有 ...

  4. BZOJ_2298_[HAOI2011]problem a_线段树

    BZOJ_2298_[HAOI2011]problem a_线段树 Description 一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低.”问最少有几个人没有说真话( ...

  5. CentOS DesktopEntry

    IBM Developer  :  https://www.ibm.com/developerworks/cn/linux/l-cn-dtef/index.html [Desktop Entry] N ...

  6. Vue 进阶之路(八)

    之前的文章我们对组件 component 进行了简单的介绍,本章我们将深入了解一下组件,并实现父子组件间的传值. <!DOCTYPE html> <html lang="e ...

  7. Ethercat 学习总结一:协议总结

    原文地址:https://blog.csdn.net/qq923433160/article/details/83781812 EtherCAT 总线的国家标准相关资料,比较详细介绍了协议: http ...

  8. 【效率神奇】Github丧心病狂的9个狠招

    Github,一个被业内朋友成为「全球最大的同性交友社区」的平台. 小时候遇到不会的字可以查新华字典.后来写作文我们可以通过作文书.或者文摘去找合适的素材.同样,写代码可以去Github上找适合自己的 ...

  9. Asp.Net Core 轻松学-多线程之取消令牌

    前言     取消令牌(CancellationToken) 是 .Net Core 中的一项重要功能,正确并合理的使用 CancellationToken 可以让业务达到简化代码.提升服务性能的效果 ...

  10. 【开发记录】如何在B/S项目中使用中国天气的实时天气功能

    好久没有更新我的博客了,正好手头有一个比较合适的项目经验可以分享出来,就是这个如何使用中国天气的天气预报功能,也正好做个项目经验记录. 功能需求 这个功能需求比较简单,就是想在网页端显示实时天气数据. ...