ServerBootStrap启动流程
Tips:代码行后面的数字对应下面中文解释的数字
通过一个简单的示例演示netty server端启动
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);// 1
EventLoopGroup workerGroup = new NioEventLoopGroup();// 2
final EchoServerHandler serverHandler = new EchoServerHandler();
try {
ServerBootstrap b = new ServerBootstrap();// 3
b.group(bossGroup, workerGroup) //4
.channel(NioServerSocketChannel.class)//5
.option(ChannelOption.SO_BACKLOG, 100)//6
.handler(new LoggingHandler(LogLevel.INFO)) //7
.childHandler(new ChannelInitializer<SocketChannel>() {//8
1:定义接收客户端连接的线程池
2:定义处理客户端请求的线程池
3:实例化一个server端启动引导类
4:将boss线程与work线程添加到ServerBootstrap中
5:定义server端的channel类型为NioServerSocketChannel
6:定义Socket为非阻塞
7:NioServerSocketChannel的ChannelPipeline成员添加LoggingHandler处理器
8:NioSocketChannel的ChannelPipeline成员添加ChannelInitializer处理器,当Server端接收到Client连接时,会初始化一个SocketChannel,然后就会回调ChannelInitializer的initChannel方法
9:往NioSocketChannel的ChannelPipeline成员添加业务Handler处理器
10:server绑定端口启动
接下来详细分析一下server端是如何启动的,启动过程中会初始化哪些信息。先看一下AbstractBootStrap#doBind(final SocketAddress localAddress)
过程
private ChannelFuture doBind(final SocketAddress localAddress) {
final ChannelFuture regFuture = initAndRegister();//1
final Channel channel = regFuture.channel();
if (regFuture.cause() != null) {
return regFuture;
}
if (regFuture.isDone()) {//2
ChannelPromise promise = channel.newPromise();
doBind0(regFuture, channel, localAddress, promise);//3
return promise;
} else {
// Registration future is almost always fulfilled already, but just in case it's not.
final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
regFuture.addListener(new ChannelFutureListener() {
1:实例化与初始化Channel信息,并将ServerSocketChannel注册到Selector选择器中
2:判断channel是否注册完成
3:调用ServerSocket.bind()底层方法绑定
注册与初始化channel:AbstractBootstrap#initAndRegister()
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
channel = channelFactory.newChannel(); //1
init(channel);//2
} 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);
}
ChannelFuture regFuture = config().group().register(channel);//15
//...省略
return regFuture;
}
private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();//3
public NioServerSocketChannel() {
this(newSocket(DEFAULT_SELECTOR_PROVIDER));//4
}
private static ServerSocketChannel newSocket(SelectorProvider provider) {
try {
return provider.openServerSocketChannel();//5
} catch (IOException e) {
throw new ChannelException(
"Failed to open a server socket.", e);
}
}
public NioServerSocketChannel(ServerSocketChannel channel) {
super(null, channel, SelectionKey.OP_ACCEPT);//6
config = new NioServerSocketChannelConfig(this, javaChannel().socket());//7
}
protected AbstractNioMessageChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent, ch, readInterestOp);
}
protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent);
this.ch = ch;//8
this.readInterestOp = readInterestOp;//9
try {
ch.configureBlocking(false);//10
} catch (IOException e) {
try {
ch.close();
} catch (IOException e2) {
logger.warn(
"Failed to close a partially initialized socket.", e2);
}
throw new ChannelException("Failed to enter non-blocking mode.", e);
}
}
protected AbstractChannel(Channel parent) {
this.parent = parent;//11
id = newId();//12