Netty源码分析系列之三:Netty启动之NioEventLoop创建(1)


一、NioEventLoop创建


Netty服务启动,最重要的事情就是做好接受客户端连接的准备。我们分别看下自定义线程以及boss线程所要完成的任务以及流程,如下所示:

在这里插入图片描述

在这里插入图片描述

这里罗列了一些比较重要的类名称及其对应的主要功能说明,以便于大家在阅读源码时可以快速了解对应类的功能:

| 类 | 作用 |

| — | — |

| ServerBootstrap | 服务端启动辅助类 |

| NioEventLoop | Nio事件处理器(Reactor模型) |

| NioEventLoopGroup | 一组Nio事件处理器(Reactor模型) |

Netty源码包中,我们首先看下 io.netty.example.echo包中的EchoServer 类,该类中包含了Netty服务启动相关代码,具体源码以及源码部分分析注释如下所示:

public final class EchoServer {

static final boolean SSL = System.getProperty(“ssl”) != null;

static final int PORT = Integer.parseInt(System.getProperty(“port”, “8007”));

public static void main(String[] args) throws Exception {

// Configure SSL.

final SslContext sslCtx;

if (SSL) {

SelfSignedCertificate ssc = new SelfSignedCertificate();

sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();

} else {

sslCtx = null;

}

//处理连接事件

EventLoopGroup bossGroup = new NioEventLoopGroup(1);

//处理读以及写的事件

EventLoopGroup workerGroup = new NioEventLoopGroup();

final EchoServerHandler serverHandler = new EchoServerHandler();

try {

//服务引导类

ServerBootstrap b = new ServerBootstrap();

b.group(bossGroup, workerGroup)

.channel(NioServerSocketChannel.class)

.option(ChannelOption.SO_BACKLOG, 100)

.handler(new LoggingHandler(LogLevel.INFO))

.childHandler(new ChannelInitializer() {

@Override

public void initChannel(SocketChannel ch) throws Exception {

//初始化channel.pipeline

ChannelPipeline p = ch.pipeline();

if (sslCtx != null) {

p.addLast(sslCtx.newHandler(ch.alloc()));

}

//p.addLast(new LoggingHandler(LogLevel.INFO));

p.addLast(serverHandler);

}

});

// 启动服务,绑定端口

ChannelFuture f = b.bind(PORT).sync();

// Wait until the server socket is closed.

f.channel().closeFuture().sync();

} finally {

// Shut down all event loops to terminate all threads.

bossGroup.shutdownGracefully();

workerGroup.shutdownGracefully();

}

}

}

在启动Netty服务过程中,创建了两个EventLoopGroup 对象,这两个对象是Netty的核心对象,其中bossGroup 用于接收请求,workerGroup用于处理请求。如下所示:

EventLoopGroup bossGroup = new NioEventLoopGroup(1);

EventLoopGroup workerGroup = new NioEventLoopGroup();

我们可以看下NioEventLoopGroup的类继承结构情况,如下所示:

在这里插入图片描述

从上图可知,NioEventLoopGroup实现了ScheduledExecutorService接口,因此它可以实现定时任务相关的功能。同时它还继承了SingleThreadEventExecutor类,从类名可以看出,这是一个单线程的线程执行器。在Netty中,通过NioEventLoopGroup的创建来达到创建NioEventLoop的目的。通过有参参数构建NioEventLoopGroup对象,实际调用的是MultithreadEventExecutorGroup的构造方法,如下所示:

protected MultithreadEventExecutorGroup(int nThreads, Executor executor,

EventExecutorChooserFactory chooserFactory, Object… args) {

if (nThreads <= 0) {

throw new IllegalArgumentException(String.format(“nThreads: %d (expected: > 0)”, nThreads));

}

if (executor == null) {

//ewDefaultThreadFactory()会创建一个线程工厂,该线程工厂的作用就是用来创建线程,同时给线程设置名称:nioEventLoop-1-XX

executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());

}

// 根据传进来的线程数,来创建指定大小的数组大小,这个数组就是用来存放NioEventLoop对象实例

children = new EventExecutor[nThreads];

for (int i = 0; i < nThreads; i ++) {

//异常标志

boolean success = false;

try {

创建nThreads个nioEventLoop保存到children数组中

children[i] = newChild(executor, args);

success = true;

} catch (Exception e) {

// TODO: Think about if this is a good exception type

throw new IllegalStateException(“failed to create a child event loop”, e);

} finally {

//异常处理

if (!success) {

for (int j = 0; j < i; j ++) {

children[j].shutdownGracefully();

}

for (int j = 0; j < i; j ++) {

EventExecutor e = children[j];

try {

while (!e.isTerminated()) {

e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);

}

} catch (InterruptedException interrupted) {

// Let the caller handle the interruption.

Thread.currentThread().interrupt();

break;

}

}

}

}

}

// 通过线程执行器选择工厂来创建一个线程执行器

chooser = chooserFactory.newChooser(children);

final FutureListener terminationListener = new FutureListener() {

@Override

public void operationComplete(Future future) throws Exception {

if (terminatedChildren.incrementAndGet() == children.length) {

terminationFuture.setSuccess(null);

}

}

};

for (EventExecutor e: children) {

e.terminationFuture().addListener(terminationListener);

}

Set childrenSet = new LinkedHashSet(children.length);

Collections.addAll(childrenSet, children);

readonlyChildren = Collections.unmodifiableSet(childrenSet);

}

对应的参数解析,如下表所示:

| 参数 | 说明 |

| — | — |

| nThreads | 创建的线程数量 |

| executor | 线程执行器(用户可自定义,没有则为null,后续进行初始化) |

| chooserFactory | 事件执行选择工厂 |

EventLoopGroup 在创建的时候会调用NioEventLoop 中的openSelector()方法。

EventLoopGroup创建本质就是创建多个NioEventLoop,这里创建NioEventLoop就是初始化一个Reactor,包括selectortaskQueue

NioEventLoop 源码如下:

public final class NioEventLoop extends SingleThreadEventLoop {

private SelectorTuple openSelector() {

final Selector unwrappedSelector;

try {

unwrappedSelector = provider.openSelector();

} catch (IOException e) {

throw new ChannelException(“failed to open a new selector”, e);

}

if (DISABLE_KEY_SET_OPTIMIZATION) {

return new SelectorTuple(unwrappedSelector);

}

Object maybeSelectorImplClass = AccessController.doPrivileged(new PrivilegedAction() {

@Override

public Object run() {

try {

return Class.forName(

“sun.nio.ch.SelectorImpl”,

false,

PlatformDependent.getSystemClassLoader());

} catch (Throwable cause) {

return cause;

}

}

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
**

[外链图片转存中…(img-Qp4nDJZ3-1715854545877)]

[外链图片转存中…(img-OweQFcsS-1715854545878)]

[外链图片转存中…(img-VB1ZYpR5-1715854545878)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值