接上一节eventLoopGroup初始化过程,本节分析服务端启动的流程。
//配置服务端的NIO线程组 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel channel) throws Exception { channel.pipeline() .addLast(new GateServerHandler()); } }) .option(ChannelOption.SO_BACKLOG, 512) .option(ChannelOption.SO_KEEPALIVE, true); //绑定端口,同步等待成功 ChannelFuture f = bootstrap.bind(port).sync(); f.channel().closeFuture().sync(); }catch (Exception e){ e.printStackTrace(); }finally { try { bossGroup.shutdownGracefully().sync(); workGroup.shutdownGracefully().sync(); } catch (InterruptedException e) { e.printStackTrace(); } }
1. bootstrap.group(bossGroup, workGroup)
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; } }
bossGroup赋值给父类AbstractBootstrap的group, workGroup赋值给ServerBootstrap的childGroup。
2. bootstrap.channel(NioServerSocketChannel.class)
public B channel(Class<? extends C> channelClass) { if (channelClass == null) { throw new NullPointerException("channelClass"); } else { return this.channelFactory((io.netty.channel.ChannelFactory)(new ReflectiveChannelFactory(channelClass))); } }
ReflectiveChannelFactory封装了传入的NioServerSocketChannel.class,再赋值给AbstractBootstrap.channelFactory
3. bootstrap.childHandler(**)
public ServerBootstrap childHandler(ChannelHandler childHandler) { if (childHandler == null) { throw new NullPointerException("childHandler"); } else { this.childHandler = childHandler; return this; } }
4. bootstrap.option
SO_KEEPALIVE:保持长链接
SO_BACKLOG:TCP三次握手ack队列的大小。更具体的内容可以参考tcp backlog参数
5. bootstrap.bind
public ChannelFuture bind(SocketAddress localAddress) { this.validate(); if (localAddress == null) { throw new NullPointerException("localAddress"); } else { return this.doBind(localAddress); } }
校验AbstractBootstrap的group和channelFactory是否为null,校验ServerBootstrap的childGroup和childHandler是否为null。重点分析下AbstractBootstrap.doBind过程
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; } }
5.1 initAndRegister初始化注册过程
final ChannelFuture initAndRegister() { Channel channel = null; try { channel = this.channelFactory.newChannel(); this.init(channel); } catch (Throwable var3) { if (channel != null) { channel.unsafe().closeForcibly(); return (new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE)).setFailure(var3); } return (new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE)).setFailure(var3); } ChannelFuture regFuture = this.config().group().register(channel); if (regFuture.cause() != null) { if (channel.isRegistered()) { channel.close(); } else { channel.unsafe().closeForcibly(); } } return regFuture; }this.newChannel方法在ReflectiveChannelFactory类中通过反射实例化NioServerSocketChannel。
NioServerSocketChannel实例化过程
public NioServerSocketChannel(java.nio.channels.ServerSocketChannel channel) { super((Channel)null, channel, 16); this.config = new NioServerSocketChannel.NioServerSocketChannelConfig(this, this.javaChannel().socket()); }
- 创建AbstractNioMessageChannel.NioMessageUnsafe
- 创建DefaultChannelPipeline,内部维护了一个AbstractChannelHandlerContext(head,tail)链表
- 设置NioServerSocketChannel的SelectionKey为OP_ACCEPT
- 设置NioServerSocketChannel为非阻塞模式
- 创建ServerSocket
this.init()
主要工作是把ServerBootstrapAcceptor放到了pipeline的链表中
p.addLast(new ChannelHandler[]{new ChannelInitializer<Channel>() { public void initChannel(final Channel ch) throws Exception { final ChannelPipeline pipeline = ch.pipeline(); ChannelHandler handler = ServerBootstrap.this.config.handler(); if (handler != null) { pipeline.addLast(new ChannelHandler[]{handler}); } ch.eventLoop().execute(new Runnable() { public void run() { pipeline.addLast(new ChannelHandler[]{new ServerBootstrap.ServerBootstrapAcceptor(ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)}); } }); } }});
this.config().group().register(channel)
group方法返回的是bossGroup,bossGroup是MultithreadEventLoopGroup的子类
public ChannelFuture register(Channel channel) { return this.next().register(channel); }
跟进this.next方法,可以看到该方法是从chooser中拿出一个eventExecutor
public EventExecutor next() { return this.chooser.next(); }
register调用了SingleThreadEventLoop类的方法,首先将NioServerSocketChannel和当前线程封装成DefaultChannelPromise对象
public ChannelFuture register(Channel channel) { return this.register((ChannelPromise)(new DefaultChannelPromise(channel, this))); }
再调用unsafe的register方法,由前面可知,unsafe就是AbstractNioMessageChannel.NioMessageUnsafe对象
public ChannelFuture register(ChannelPromise promise) { ObjectUtil.checkNotNull(promise, "promise"); promise.channel().unsafe().register(this, promise); return promise; }
- AbstractChannel.this.doRegister()将NioServerSocketChannel注册到当前线程绑定的selector上
- AbstractChannel.this.pipeline.invokeHandlerAddedIfNeeded()如果自定义了handler(注意不是childHandler),将handler加到pipeline的链表中
- AbstractChannel.this.pipeline.fireChannelRegistered(),在head->tail的调用链上传递注册事件
boolean firstRegistration = this.neverRegistered; AbstractChannel.this.doRegister(); this.neverRegistered = false; AbstractChannel.this.registered = true; AbstractChannel.this.pipeline.invokeHandlerAddedIfNeeded(); this.safeSetSuccess(promise); AbstractChannel.this.pipeline.fireChannelRegistered(); if (AbstractChannel.this.isActive()) { if (firstRegistration) { AbstractChannel.this.pipeline.fireChannelActive(); } else if (AbstractChannel.this.config().isAutoRead()) { this.beginRead(); } }
5.2 AbstractBootstrap.doBind
再回到AbstractBootstrap.doBind方法上,跟进doBind0 -> AbstractChannel.bind -> DefaultChannelPipeline.bind
public final ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) { return this.tail.bind(localAddress, promise); }
this.findContextOutbound方法从tail开始循环向前找到属性outbound为true的AbstractChannelHandlerContext,返回HeadContext,调用headContext的bind方法
final AbstractChannelHandlerContext next = this.findContextOutbound(); EventExecutor executor = next.executor(); if (executor.inEventLoop()) { next.invokeBind(localAddress, promise); }
跟进unsafe.bind方法
try { AbstractChannel.this.doBind(localAddress); } catch (Throwable var5) { this.safeSetFailure(promise, var5); this.closeIfClosed(); return; } if (!wasActive && AbstractChannel.this.isActive()) { this.invokeLater(new Runnable() { public void run() { AbstractChannel.this.pipeline.fireChannelActive(); } }); }
AbstractChannel.this.doBind(localAddress)调用java nio的ServerSocketChannelImpl绑定了地址和端口
protected void doBind(SocketAddress localAddress) throws Exception { if (PlatformDependent.javaVersion() >= 7) { this.javaChannel().bind(localAddress, this.config.getBacklog()); } else { this.javaChannel().socket().bind(localAddress, this.config.getBacklog()); } }
AbstractChannel.this.pipeline.fireChannelActive在pipeline链表上传播Active和Read事件
public void channelActive(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelActive(); this.readIfIsAutoRead(); }
服务端完成绑定,并且激活channel和等待客户端read事件