netty启动源码阅读
前言
netty是一个高性能的网络框架,为什么高性能,需要读者自行了解一下BIO,NIO 等java的IO发展。今天只分享netty的服务启动源码阅读。
netty服务启动示例代码
在netty官方网站里提供了很多netty的用例,供测试使用,我们今天就对这段代码开始debug
这两个源码都在 io.netty.example.echo 包下
启动类示例分析
看启动类的main函数
代码很简洁分4块来阅读,先简单了解一下这4块主要做什么,然后详细分析
1 可以看到是创建了两个EventLoopGroup 对象 ,这两个对象是netty的核心对象,一个负责接收请求,一个负责请求的读写处理。
2 这是netty服务的启动类,这个类非常关键,这样比喻,它就像一台电脑,由很多的组件组成,这些组件是什么呢,可以看到他的group方法是配置上边创建的EventLoopGroup对象,channel方法传入的是NioServerSocketChannel,是创建服务端的通道对象。
option是配置连接的其他属性,handler是配置处理接收请求EventLoopGroup对象处理器,childHandler是配置I/O请求的处理器,可以看到childHandler会传入一个ChannelInitializer对象,这个对象是初始化读写通道的。处理请求的通道初始化会在bind方法中实现。
3 bind就是今天分享的重点,debug也是从这开始。
4 最后一块就是优雅关闭服务器。
处理器示例分析
这个处理器我们可以看到是用来处理I/0时的处理器,从继承类看到是处理的入站事件,入站就是服务端接收到客户端的请求。
3个方法,channelRead就是对请求的具体处理,第二个参数就是消息对象,channelReadComplete是处理完之后的处理,exceptionCaught是发生异常的处理方法。
NioEventLoopGroup
接下来我们看看这个对象的初始化,到底是做了是什么
继续下走到这
protected MultithreadEventExecutorGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, Object... args) {
this.terminatedChildren = new AtomicInteger();
this.terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE);
if (nThreads <= 0) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
} else {
if (executor == null) {
executor = new ThreadPerTaskExecutor(this.newDefaultThreadFactory());
}
this.children = new EventExecutor[nThreads];
int j;
for(int i = 0; i < nThreads; ++i) {
boolean success = false;
boolean var18 = false;
try {
var18 = true;
this.children[i] = this.newChild((Executor)executor, args);
success = true;
var18 = false;
} catch (Exception var19) {
throw new IllegalStateException("failed to create a child event loop", var19);
} finally {
if (var18) {
if (!success) {
int j;
for(j = 0; j < i; ++j) {
this.children[j].shutdownGracefully();
}
for(j = 0; j < i; ++j) {
EventExecutor e = this.children[j];
try {
while(!e.isTerminated()) {
e.awaitTermination(2147483647L, TimeUnit.SECONDS);
}
} catch (InterruptedException var20) {
Thread.currentThread().interrupt();
break;
}
}
}
}
}
if (!success) {
for(j = 0; j < i; ++j) {
this.children[j].shutdownGracefully();
}
for(j = 0; j < i; ++j) {
EventExecutor e = this.children[j];
try {
while(!e.isTerminated()) {
e.awaitTermination(2147483647L, TimeUnit.SECONDS);
}
} catch (InterruptedException var22) {
Thread.currentThread().interrupt();
break;
}
}
}
}
this.chooser = chooserFactory.newChooser(this.children);
FutureListener<Object> terminationListener = new FutureListener<Object>() {
public void operationComplete(Future<Object> future) throws Exception {
if (MultithreadEventExecutorGroup.this.terminatedChildren.incrementAndGet() == MultithreadEventExecutorGroup.this.children.length) {
MultithreadEventExecutorGroup.this.terminationFuture.setSuccess((Object)null);
}
}
};
EventExecutor[] var24 = this.children;
j = var24.length;
for(int var26 = 0; var26 < j; ++var26) {
EventExecutor e = var24[var26];
e.terminationFuture().addListener(terminationListener);
}
Set<EventExecutor> childrenSet = new LinkedHashSet(this.children.length);
Collections.addAll(childrenSet, this.children);
this.readonlyChildren = Collections.unmodifiableSet(childrenSet);
}
}
这段代码才是我们核心代码,代码很长自上而下看,校验不去看,
this.children = new EventExecutor[nThreads];
int j;
for(int i = 0; i < nThreads; ++i) {
boolean success = false;
boolean var18 = false;
try {
var18 = true;
this.children[i] = this.newChild((Executor)executor, args);
success = true;
var18 = false;
} catch (Exception var19) {
throw new IllegalStateException("failed to create a child event loop", var19);
} finally {
if (var18) {
if (!success) {
int j;
for(j = 0; j < i; ++j) {
this.children[j].shutdownGracefully();
}
for(j = 0; j < i; ++j) {
EventExecutor e = this.children[j];
try {
while(!e.isTerminated()) {
e.awaitTermination(2147483647L, TimeUnit.SECONDS);
}
} catch (InterruptedException var20) {
Thread.currentThread().interrupt();
break;
}
}
}
}
}
if (!success) {
for(j = 0; j < i; ++j) {
this.children[j].shutdownGracefully();
}
for(j = 0; j < i; ++j) {
EventExecutor e = this.children[j];
try {
while(!e.isTerminated()) {
e.awaitTermination(2147483647L, TimeUnit.SECONDS);
}
} catch (InterruptedException var22) {
Thread.currentThread().interrupt();
break;
}
}
}
}
这块代码根据传进来的参数,如果不传的默认是cpu*2的线程数去创建线程池组就是这行代码 实际上就是每一个EventLoop对象
this.children[i] = this.newChild((Executor)executor, args);
如果发生异常的话一个个的再去关闭线程池
this.chooser = chooserFactory.newChooser(this.children);
这块代码是根据这个线程池数据创建一个线程池选择器我们跟进去看看
private DefaultEventExecutorChooserFactory() {
}
public EventExecutorChooser newChooser(EventExecutor[] executors) {
return (EventExecutorChooser)(isPowerOfTwo(executors.length) ? new DefaultEventExecutorChooserFactory.PowerOfTwoEventExecutorChooser(executors) : new DefaultEventExecutorChooserFactory.GenericEventExecutorChooser(executors));
}
private static boolean isPowerOfTwo(int val) {
return (val & -val) == val;
}
private static final class GenericEventExecutorChooser implements EventExecutorChooser {
private final AtomicInteger idx = new AtomicInteger();
private final EventExecutor[] executors;
GenericEventExecutorChooser(EventExecutor[] executors) {
this.executors = executors;
}
public EventExecutor next() {
return this.executors[Math.abs(this.idx.getAndIncrement() % this.executors.length)];
}
}
private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
private final AtomicInteger idx = new AtomicInteger();
private final EventExecutor[] executors;
PowerOfTwoEventExecutorChooser(EventExecutor[] executors) {
this.executors = executors;
}
public EventExecutor next() {
return this.executors[this.idx.getAndIncrement() & this.executors.length - 1];
}
}
这是两种线程池选择器的实现。
再返回接着看
FutureListener<Object> terminationListener = new FutureListener<Object>() {
public void operationComplete(Future<Object> future) throws Exception {
if (MultithreadEventExecutorGroup.this.terminatedChildren.incrementAndGet() == MultithreadEventExecutorGroup.this.children.length) {
MultithreadEventExecutorGroup.this.terminationFuture.setSuccess((Object)null);
}
}
};
EventExecutor[] var24 = this.children;
j = var24.length;
for(int var26 = 0; var26 < j; ++var26) {
EventExecutor e = var24[var26];
e.terminationFuture().addListener(terminationListener);
}
Set<EventExecutor> childrenSet = new LinkedHashSet(this.children.length);
Collections.addAll(childrenSet, this.children);
this.readonlyChildren = Collections.unmodifiableSet(childrenSet);
看着段代码是给线程池组的每个线程池创建一个关闭的监听器。
再把这个NioEventLoopGroup对象放到一个LinkedHashSet集合中。这个阅读到这基本完成了。当然我们还没有分析EventLoop对象是做什么的,后边到阅读bind的时候就会看到。
ServerBootstrap
接下来看看这个启动类
private static final InternalLogger logger = InternalLoggerFactory.getInstance(ServerBootstrap.class);
private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap();
private final Map<AttributeKey<?>, Object> childAttrs = new LinkedHashMap();
private final ServerBootstrapConfig config = new ServerBootstrapConfig(this);
private volatile EventLoopGroup childGroup;
private volatile ChannelHandler childHandler;
public ServerBootstrap() {
}
private ServerBootstrap(ServerBootstrap bootstrap) {
super(bootstrap);
this.childGroup = bootstrap.childGroup;
this.childHandler = bootstrap.childHandler;
synchronized(bootstrap.childOptions) {
this.childOptions.putAll(bootstrap.childOptions);
}
synchronized(bootstrap.childAttrs) {
this.childAttrs.putAll(bootstrap.childAttrs);
}
}
public ServerBootstrap group(EventLoopGroup group) {
return this.group(group, group);
}
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
super.group(parentGroup);
if (childGroup == null) {
throw new NullPointerException("childGroup");
} else if (this.childGroup != null) {
throw new IllegalStateException("childGroup set already");
} else {
this.childGroup = childGroup;
return this;
}
}
group 方法,将 boss 和 worker 传入,boss 赋值给 group 属性,worker 赋值给 childGroup 属性。
注意其中的 ServerBootstrapConfig 对象,这个对象将会在后面起很大作用。
bind调试
从这开始我们就进行debug
public ChannelFuture bind(SocketAddress localAddress) {
this.validate();
if (localAddress == null) {
throw new NullPointerException("localAddress");
} else {
return this.doBind(localAddress);
}
}
private ChannelFuture doBind(final SocketAddress localAddress) {
final ChannelFuture regFuture = this.initAndRegister();
final Channel channel = regFuture.channel();
if (regFuture.cause() != null) {
return regFuture;
} else if (regFuture.isDone()) {
ChannelPromise promise = channel.newPromise();
doBind0(regFuture, channel, localAddress, promise);
return promise;
} else {
final AbstractBootstrap.PendingRegistrationPromise promise = new AbstractBootstrap.PendingRegistrationPromise(channel);
regFuture.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
Throwable cause = future.cause();
if (cause != null) {
promise.setFailure(cause);
} else {
promise.registered();
AbstractBootstrap.doBind0(regFuture, channel, localAddress, promise);
}
}
});
return promise;
}
}
可以看到走到了doBind,doBind方法中分为几块,我们先看第一块initAndRegister(),初始化和注册,从方法名上看是初始化通道和注册通道的一个方法,debug到方法体继续看下去