前言
上一篇分析了服务端启动类的源码,接下来我们在上一篇的代码的基础上,一步一步的看一下启动过程中是如何运作的。
由于启动过程代码调用链较长,所以分为两部分来分析。
本文分析的是启动过程中的初始化部分。
正文
io.netty.example.echo.EchoServer
// 启动类中这一句是开始启动,我们跟进到bind方法中
ChannelFuture f = b.bind(PORT).sync();
io.netty.bootstrap.AbstractBootstrap
public ChannelFuture bind(SocketAddress localAddress) {
// 验证ServerBootstrap传进来的参数
validate();
// 继续跟进去
return doBind(ObjectUtil.checkNotNull(localAddress, "localAddress"));
}
private ChannelFuture doBind(final SocketAddress localAddress) {
// 初始化和注册动作,返回Future(异步操作),见另外一个代码块
final ChannelFuture regFuture = initAndRegister();
final Channel channel = regFuture.channel();
// 如果注册过程中抛错了,直接返回
if (regFuture.cause() != null) {
return regFuture;
}
// 判断注册future有没有完成(可以看到,除非是失败,最后都会调用doBind0())
if (regFuture.isDone()) {
// 成功结束了的话,执行dobind0方法
ChannelPromise promise = channel.newPromise(); // Promise,一种可以写的Future
doBind0(regFuture, channel, localAddress, promise);
return promise;
} else {
final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
// 注册没有结束的话,添加一个监听,在回调函数里面判断成功还是失败
regFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
Throwable cause = future.cause();
if (cause != null) {
promise.setFailure(cause);
} else {
promise.registered();
doBind0(regFuture, channel, localAddress, promise);
}
}
});
return promise;
}
}
io.netty.bootstrap.AbstractBootstrap
// 初始化并且注册过程
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
// 这个channelFactory是ReflectiveChannelFactory,在创建ServerBootStrap的时候注册的.channel(NioServerSocketChannel.class),可以在启动类中跟进去看源码
// 所以这个channel是NioServerSocketChannel
channel = channelFactory.newChannel();
// 【重要代码】为NioServerSocketChannel添加handler
init(channel);
} catch (Throwable t) {
// 异常处理部分,可以忽略
if (channel != null) {
channel.unsafe().closeForcibly();
return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
}
return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
}
// 【重要代码】异步注册到NioEventLoop(selector)中,这部分我们在下一篇中详细分析
ChannelFuture regFuture = config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
// 具体初始化过程
io.netty.bootstrap.ServerBootstrap
@Override
void init(Channel channel) {
// 根据初始化的option,设置channel的参数
setChannelOptions(channel, newOptionsArray(), logger);
// 根据初始化的attr,设置channel的属性
setAttributes(channel, attrs0().entrySet().toArray(EMPTY_ATTRIBUTE_ARRAY));
ChannelPipeline p = channel.pipeline();
// 下面四个都是workerGroup的属性
final EventLoopGroup currentChildGroup = childGroup;
final ChannelHandler currentChildHandler = childHandler;
final Entry<ChannelOption<?>, Object>[] currentChildOptions;
synchronized (childOptions) {
currentChildOptions = childOptions.entrySet().toArray(EMPTY_OPTION_ARRAY);
}
final Entry<AttributeKey<?>, Object>[] currentChildAttrs = childAttrs.entrySet().toArray(EMPTY_ATTRIBUTE_ARRAY);
p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(final Channel ch) {
final ChannelPipeline pipeline = ch.pipeline();
ChannelHandler handler = config.handler();
if (handler != null) {
// 这里添加的是注册时候的handler :LoggingHandler
pipeline.addLast(handler);
}
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
// pipeline异步添加一个负责接收客户端事件的handler:ServerBootstrapAcceptor,并且把workerGroup的属性当做参数传进去,
//所以这个ServerBootstrapAcceptor是netty默认会加到pipeline中,不用我们手动添加
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
}