技术干货

【第15篇】netty服务端初始化流程详细分析

2019-05-28  本文已影响20人  爱学习的蹭蹭

1、 Channel与ChannelHandlerContext

New and noteworthy in 4.1 请截图

ChannelHandlerContext
ChannelHandlerContext

2、 初始化流程

服务端初始化的步骤
1、创建ServerBootstrap启动辅助类,通过Builder模式进行参数配置;
2、创建并绑定Reactor线程池EventLoopGroup;
4、设置并绑定服务端Channel通道类型;
5、绑定服务端通道数据处理器责任链Handler;

3、ServerBootstrap初始化

public class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, ServerChannel> {
    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;
}

image.png
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap b= new ServerBootstrap();
b.group(boosGroup,workGroup)

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;
    }
}
public B group(EventLoopGroup group) {
    if(group == null) {
        throw new NullPointerException("group");
    } else if(this.group != null) {
        throw new IllegalStateException("group set already");
    } else {
        this.group = group;
        return this;
    }
}

4、Channel通道初始化

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)));
    }
}

private final Class<? extends T> clazz;

public ReflectiveChannelFactory(Class<? extends T> clazz) {
    if(clazz == null) {
        throw new NullPointerException("clazz");
    } else {
        this.clazz = clazz;
    }
}

public T newChannel() {
    try {
        return (Channel)this.clazz.newInstance();
    } catch (Throwable var2) {
        throw new ChannelException("Unable to create Channel from class " + this.clazz, var2);
    }
}
public B channelFactory(ChannelFactory<? extends C> channelFactory) {
    if(channelFactory == null) {
        throw new NullPointerException("channelFactory");
    } else if(this.channelFactory != null) {
        throw new IllegalStateException("channelFactory set already");
    } else {
        this.channelFactory = channelFactory;
        return this;
    }
}

5、Channel通道实例化

ServerBootstrap.bind() -> AbstractBootstrap.doBind() -> AbstractBootstrap.initAndRegister() -> ChannelFactory.newChannel();

public T newChannel() {
    try {
        return (Channel)this.clazz.newInstance();
    } catch (Throwable var2) {
        throw new ChannelException("Unable to create Channel from class " + this.clazz, var2);
    }
}
public NioServerSocketChannel() {
    this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}
public NioServerSocketChannel(java.nio.channels.ServerSocketChannel channel) {
    super((Channel)null, channel, 16);
    this.config = new NioServerSocketChannel.NioServerSocketChannelConfig(this, this.javaChannel().socket());
}

AbstractNioChannel 中的属性:

AbstractChannel 的属性:

NioServerSocketChannel 中的属性:

ServerSocketChannelConfig config = new NioServerSocketChannelConfig(this, javaChannel().socket())

6、Channel通道注册

final ChannelFuture initAndRegister() {
    // 去掉非关键代码
    final Channel channel = channelFactory().newChannel();
    init(channel);
    ChannelFuture regFuture = group().register(channel);
}
private void register0(ChannelPromise promise) {
    boolean firstRegistration = neverRegistered;
    doRegister();
    neverRegistered = false;
    registered = true;
    safeSetSuccess(promise);
    pipeline.fireChannelRegistered();
    // Only fire a channelActive if the channel has never been registered. This prevents firing
    // multiple channel actives if the channel is deregistered and re-registered.
    if (firstRegistration && isActive()) {
        pipeline.fireChannelActive();
    }
}
@Override
protected void doRegister() throws Exception {
    // 省略错误处理
    selectionKey = javaChannel().register(eventLoop().selector, 0, this);
}

7 handler处理器的添加过程

bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
 protected void initChannel(SocketChannel socketChannel) throws Exception {
    socketChannel.pipeline().addLast(new TimeServerHandler());
     }
});
public ServerBootstrap childHandler(ChannelHandler childHandler) {
    if(childHandler == null) {
        throw new NullPointerException("childHandler");
    } else {
        this.childHandler = childHandler;
        return this;
    }
}
@Override
void init(Channel channel) throws Exception {
    ...
    ChannelPipeline p = channel.pipeline();

    final EventLoopGroup currentChildGroup = childGroup;
    final ChannelHandler currentChildHandler = childHandler;
    final Entry<ChannelOption<?>, Object>[] currentChildOptions;
    final Entry<AttributeKey<?>, Object>[] currentChildAttrs;

    p.addLast(new ChannelInitializer<Channel>() {
        @Override
        public void initChannel(Channel ch) throws Exception {
            ChannelPipeline pipeline = ch.pipeline();
            ChannelHandler handler = handler();
            if (handler != null) {
                pipeline.addLast(handler);
            }
            pipeline.addLast(new ServerBootstrapAcceptor(
                    currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
        }
    });
}
public void channelRead(ChannelHandlerContext ctx, Object msg) {
    final Channel child = (Channel) msg;
    child.pipeline().addLast(childHandler);
    ...
    childGroup.register(child).addListener(...);
}

8、 OIO(掌握点)

9、 lsof命令

10、总结

Netty服务端的初始化主要是创建初始化辅助类ServerBootstrap,并对辅助类的相关参数进行初始化包括EventLoop线程池,Channle通道类型和ChannleHandler通道处理器等;在调用bind()方法进行端口绑定时,会根据ServerBootsrap中的初始化参数启动服务端,具体的启动流程为:

推荐学习博客

此文章内容来自服务端初始化和个人学习过程中整理记录笔记的摘要

上一篇 下一篇

猜你喜欢

热点阅读