大数据深入浅出Netty源码剖析程序员

netty源码走读(服务端Channel创建流程)

2019-01-30  本文已影响1人  gfgao

概念:

NioEventLoop

Channel:

ByteBuf:

PipeLine:

ChannelHandler:

服务器端启动流程:

创建服务器端`Channel`->初始化服务器端`Channel`->注册`Selector`->端口绑定

创建服务器端Channel从用户代码的bind()方法入口,调用initAndRegister()方法,在initAndRegister()方法中,调用newChannel()方法,创建服务器端Channel.
ChannelFuture future = bootstrap.bind(8090).sync();

调用流程

整个调用过程逻辑相对比较清晰。

    final ChannelFuture initAndRegister() {
        Channel channel = null;
        try {
            channel = channelFactory.newChannel();
            init(channel);
        } catch (Throwable t) {

我们跟进newChannel()方法,看一下Channel的创建过程.

    @Override
    public T newChannel() {
        try {
            return clazz.getConstructor().newInstance();
        } catch (Throwable t) {
            throw new ChannelException("Unable to create Channel from class " + clazz, t);
        }
    }

Channel的创建是以反射的方式创建。那我们就看一下clazz对应的实例是谁,从而也就知道了反射后创建的Channel的具体类型了。

public class ReflectiveChannelFactory<T extends Channel> implements ChannelFactory<T> {

    private final Class<? extends T> clazz;

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

clazz是从外部接收的一个Class实例。既然是外部接收的,就看一下我们的Server端代码

bootstrap.group(master,worker)
                .channel(NioServerSocketChannel.class)

我们跟进channel()方法

    public B channel(Class<? extends C> channelClass) {
        if (channelClass == null) {
            throw new NullPointerException("channelClass");
        }
        return channelFactory(new ReflectiveChannelFactory<C>(channelClass));
    }

我们传进去的channelClass也就是NioServerSocketChannel.class,交给了ReflectiveChannelFactory。这样就知道了我们服务端创建的是NioServerSocketChannel。我们跟进NioServerSocketChannel类,看一下这个类的实例化过程。

由于在利用反射创建NioServerSocketChannel时候,channel = channelFactory.newChannel();没有传参进去,我们需要跟进NioServerSocketChannel的无参构造函数。

    public NioServerSocketChannel() {
        this(newSocket(DEFAULT_SELECTOR_PROVIDER));
    }

跟进this构造函数

    public NioServerSocketChannel(ServerSocketChannel channel) {
        super(null, channel, SelectionKey.OP_ACCEPT);
        config = new NioServerSocketChannelConfig(this, javaChannel().socket());
    }

抽丝剥茧,跟进newSocket()方法,并将newSocket的返回值ServerSocketChannel作为参数传递给NioServerSocketChannel(ServerSocketChannel channel)

    private static ServerSocketChannel newSocket(SelectorProvider provider) {
        try {
            /**
             *  Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in
             *  {@link SelectorProvider#provider()} which is called by each ServerSocketChannel.open() otherwise.
             *
             *  See <a href="https://github.com/netty/netty/issues/2308">#2308</a>.
             */
            return provider.openServerSocketChannel();
        } catch (IOException e) {
            throw new ChannelException(
                    "Failed to open a server socket.", e);
        }
    }

newSocket中,nettyjdk底层Socket建立了连接。

在初始化NioServerSocketChannel时,创建了NioServerSocketChannelConfig,主要负责给创建的jdk底层的Socket的TCP相关配置。

我们跟进

public NioServerSocketChannel(ServerSocketChannel channel) {
        super(null, channel, SelectionKey.OP_ACCEPT);

进入父类的构造函数

    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;
        this.readInterestOp = readInterestOp;
        try {
            ch.configureBlocking(false);
        } catch (IOException e) {

当我们看到ch.configureBlocking(false)这行代码的时候,就知道了创建出来的Socket是非阻塞模式。

继续跟进父类

    protected AbstractChannel(Channel parent) {
        this.parent = parent;
        id = newId();
        unsafe = newUnsafe();
        pipeline = newChannelPipeline();
    }

创建了Channel的唯一标识id,unsafe封装了Channel和底层相关的操作,pipeline封装了跟服务端程序相关的逻辑链。至此服务端NioServerSocketChannel创建成功。

上一篇下一篇

猜你喜欢

热点阅读