netty之源码浅析

ChannelFactory 和 Channel 类型的确定

1.ReflectiveChannelFactory类保存了NioSocketChannel的class类,用于反射生成NioSocketChannel

2.channel(NioSocketChannel.class)返回了一个有channelFactory = new ReflectiveChannelFactory()的AbstractBootstrap对象

Channel 实例化

1. Channel实例化是在bind()的方法中完成的,根据bind()方法链路跟踪,最后到达doResolveAndConnect方法,

private ChannelFuture doResolveAndConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) {...}

这里就是关键了。

    首先:final ChannelFuture regFuture = initAndRegister();  点进去可以看到channel = channelFactory.newChannel();  这里的channelFactory是不是就是ReflectiveChannelFactory,然后通过反射生成NioSocketChannel,生成对象的同时会调NioSocketChannel的默认构造方法,找到NioSocketChannel的

private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();
public NioSocketChannel() {
    this(DEFAULT_SELECTOR_PROVIDER);
}

这个DEFAULT_SELECTOR_PROVIDER其实就是java中的NIO操作selector的一个provider(),接着会调用 newSocket 来打开一个新的 Java NIO SocketChannel,接着调用this继续,可以发现parent为null,跟踪到最后面发现其实就是设置了ch,设置了readInterestOp为读事件,设置ch为非阻塞而已,接着继续调用super(),这里会新建2个属性unsafe(封装了对 Java 底层 Socket 的操作)和pipeline,所以这样看来每个channel是会对应一个自己的unsafe和pipeline,这样一个初始化的channel就生成了,还是略微有点复杂。

   这里有两个初始化关注一下:

   unsafe:我们发现newUnsafe()其实是个抽象方法,那么AbstractChannel的子类中肯定实现了这个方法,然后我们知道生成的类型是NioSocketChannel,找到该方法,发现调用new NioSocketChannelUnsafe(),其实是一个 NioSocketChannelUnsafe 的实例。

扫描二维码关注公众号,回复: 4749505 查看本文章

   pipeline:这里简单来说就是pipleline中保存了channel和tail,head的属性,tail和head是双向链表的形式。

   根据类的关系图可知tail是Inbound,而head是outbound。

   然后:刚才其实才仅仅看了channelFactory.newChannel()实例化过程,接下来就该初始化了,调用init(),然后有这行代码p.addLast(config.handler()); 最终发现config.handler()实际取的就是AbstractBootStrap中的ChannelHandler handler属性并且这个属性是在客户端调用handler(...)方法设值的,类型为ChannelInitializer 实例,因此这时候pipleline的结果为

head-> ChannelInitializer->tail。

我们在对addLaset()方法进行分析,如果handler不是重名的情况下,会创建一个AbstractChannelHandlerContext,其实就是把handler封装成了DefaultChannelHandlerContext对象,这里有两个Inbound和outbound属性的判断,根据类图可以知道ChannelInitializer实现了Inbound,所有Inbound=true,outbound=false,最后调用addLast0插入到tail之前。

   最后:这样实例化和初始化channel2个步骤完成了,接下来就是注册的过程了,注册过程比较简单,就是把clannel注册到nioEventLoop的selector上,当然这里要先涉及到nioEventLoop的初始化操作(这步操作比较简单,系统会根据设置的线程数量去初始化线程池大小,如果没有设置就取cpu数*2),一个nioEventLoop是绑定了一个selector,而源码中的next()实际就是获取一个当前可用的nioEventLoop对象。

自定义channel添加过程

  自定义channel在AbstractChannel的register0中完成添加,也就是说在channel实例化和初始化后就会添加自定义的channel,pipeline.fireChannelRegistered();这行代码进行跟踪,会发现根据findContextInbound()会找到ChannelInitializer,然后调用ChannelInitializer的channelRegistered,关键来了,channelRegistered的方法又会调用initChannel,而这个方法是抽象方法,由我们自定义的channel实现,所以这里就加入了自定义channel,最后ChannelInitializer会remove自己,所以此时就变成了head-> myHandler->tail,此时自定义添加channel高一段落。

客户端连接过程在channel实例,初始化和注册和添加完成后,接下来就是真正的connect了)

  分析BootStrap的doResolveAndConnect0方法,最后会调用channel.connect,此时的channel其实是NioSocketChannel,然后会进入AbstractChannelHandlerContext的connect,看这行代码final AbstractChannelHandlerContext next = findContextOutbound(); ,无非就是找到第一个outbound为true的ChannelHandler,这列可以知道第一个就是HeadContext,然后最后就是unsafe.connect(remoteAddress, localAddress, promise); 这个一看就知道是调用底层java的AbstractNioUnsafe的connect,根据doConnect进入NioSocketChannel的doConnect找到真正的方法boolean connected = SocketUtils.connect(javaChannel(), remoteAddress); 到此为止客户端的connect才算完成。

服务端Channel实例化

  大概的流程跟客户端一致,只是事件变成了SelectionKey.OP_ACCEPT,还有值得注意的就是原本newUnsafe()应该返回AbstractChannel的newUnsafe,然而AbstractNioMessageChannel又继承了AbstractChannel,所以最终调用的是AbstractNioMessageChannel的newUnsafe(),返回NioMessageUnsafe实例。

bossGroup和workerGroup

   这里的bossGroup主要处理accept连接,当收到accept事件后,会调用ServerBootstrapAcceptor的channelRead方法,然后就会找到workerGroup的某个eventLoop和新接入进来NioSocketChannel关联,之后就用workerGroup中的某个线程处理相应的io事件。

    要关注的是,bossGroup初始化时,即调用init(channel);会向NioServerSocketChannel的pipline添加ChannelInitializer,之后调用config().group().register(channel);就把NioServerSocketChannel注册到了bossGroup的一个线程中,注册成功后又会执行pipeline.fireChannelRegistered();这个关键代码,找到第一个outbound为true的channelContext,即ChannelInitializer并调用channelRegistered(),所以此时pipline就变成了head->LoggerHandler->ServerBootstrapAcceptor->tail。

    而wokerGroup则是通过ServerBootstrapAcceptor中channelRead和接入进来的NioSocketChannel关联起来的,handler的添加基本相同,这里就不做过多解释了。

  

猜你喜欢

转载自blog.csdn.net/oushitian/article/details/84065348
今日推荐