一. 代码下载
Netty代码下载和编译参考前一篇Netty文章
https://blog.51cto.com/483181/2112163
创新互联是一家集网站建设,东源企业网站建设,东源品牌网站建设,网站定制,东源网站建设报价,网络营销,网络优化,东源网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。
二. 服务器代码分析
2.1 服务器代码编写
一般Netty服务器端这样编写
EventLoopGroup bossGroup = new NioEventLoopGroup(); //1. 实例化NioEventLoopGroup对象
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap(); //2.
b.group(bossGroup, workerGroup) //3.
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new FixedLengthFrameDecoder(20));
}
});
ChannelFuture f = b.bind(port).sync(); //4.
f.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
2.2 NioEventLoopGroup
2.2.1 NioEventLoopGroup继承关系
一步步来看,首先看第一个注释,初始化NioEventLoopGroup对象
EventLoopGroup bossGroup = new NioEventLoopGroup(); //1. 实例化NioEventLoopGroup对象
下图是NioEventLoopGroup的类继承图,包含类成员和方法,比较详细。 这个功能是IntelliJ 自带的。
右击NioEventLoopGroup类名,选择Diagrams->Show Diagram->上面有f,m的按钮,分别对应field和method。
如下:

2.2.2 NioEventLoopGroup构造函数
public NioEventLoopGroup() {
this(0);
}
public NioEventLoopGroup(int nThreads) {
this(nThreads, (Executor) null);
}
public NioEventLoopGroup(int nThreads, Executor executor) {
this(nThreads, executor, SelectorProvider.provider());
}
public NioEventLoopGroup(
int nThreads, Executor executor, final SelectorProvider selectorProvider) {
this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);
}
public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider,
final SelectStrategyFactory selectStrategyFactory) {
super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
}
我们可以看到几点
- NioEventLoopGroup采用的是构造函数重载的方式,以适应不同的初始化场景
- Executor传的是null
- SelectorProvider用的是SelectorProvider.provider()
- 然后把构造好的参数都传给父类MultithreadEventLoopGroup (继承关系可以看上图)
2.2.3 SelectorProvider.provider()
private static SelectorProvider provider = null;
public static SelectorProvider provider() {
synchronized (lock) {
if (provider != null)
return provider;
return AccessController.doPrivileged(
new PrivilegedAction() {
public SelectorProvider run() {
if (loadProviderFromProperty())
return provider;
if (loadProviderAsService())
return provider;
provider = sun.nio.ch.DefaultSelectorProvider.create();
return provider;
}
});
}
}
public class DefaultSelectorProvider {
private DefaultSelectorProvider() {
}
public static SelectorProvider create() {
return new KQueueSelectorProvider();
}
}
public class KQueueSelectorProvider extends SelectorProviderImpl {
public KQueueSelectorProvider() {
}
public AbstractSelector openSelector() throws IOException {
return new KQueueSelectorImpl(this);
}
}
这段代码我们也可以看到几点:
- SelectorProvider provider是一个单例,static类型
- SelectorProvider.provider的实现,产生了一个KQueueSelectorProvider
- KQueueSelectorProvider的openSelector会生成一个KQueueSelectorImpl
这个先记下来,也许后面分析会有用,继续分析MultithreadEventLoopGroup的构造函数。
2.2.4 MultithreadEventLoopGroup
protected MultithreadEventLoopGroup(int nThreads, ThreadFactory threadFactory, Object... args) {
super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, threadFactory, args);
}
private static final int DEFAULT_EVENT_LOOP_THREADS;
static {
DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
"io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
}
上面这段代码我们可以看到这几点:
- 如果我们实例化NioEventLoopGroup没有传入参数,也就是没有nThreads,那么就会采用默认的DEFAULT_EVENT_LOOP_THREADS
DEFAULT_EVENT_LOOP_THREADS如果没有配置io.netty.eventLoopThreads的话,一般是cpu核数*2 - MultithreadEventLoopGroup的实例化方法是继续调用父类的初始化方法。
继续父类MultithreadEventExecutorGroup
2.2.5 MultithreadEventExecutorGroup
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
...
children = new EventExecutor[nThreads]; //1. 实例化children数组
for (int i = 0; i < nThreads; i ++) { //2. 循环初始化children
boolean success = false;
try {
children[i] = newChild(executor, args);
success = true;
} catch (Exception e) {
throw new IllegalStateException("failed to create a child event loop", e);
} finally {
...
}
}
chooser = chooserFactory.newChooser(children); //3. 实例化chooser
final FutureListener