当前位置:首页 >> 中医保健 >> 手撕Netty源码 之客户端启动类Bootstrap源码比对

手撕Netty源码 之客户端启动类Bootstrap源码比对

发布时间:2024-01-12

el的在结构上缓冲器。

同时,传到给定,parent的最大值配置文件为null,ch为之前初始解构newSocket()原理成立的ja NIO的SocketChannel对脚,因此新成立的NioSocketChannel对脚里的parent暂时是null。说明了字符如下。

接着时会初始解构父类AbstractNioChannel的在结构上缓冲器,并传到实际给定readInterestOp=SelectionKey.OP_READ。

仍要时会初始解构父类AbstractChannel的在结构上缓冲器。

至此,NioSocketChannel就收尾了格式解构,我们可以略微阐释一下NioSocketChannel格式解构所花钱的工作具体内容。

(1)初始解构NioSocketChannel.newSocket(DEFAULT_SELECTOR_PROVIDER)锁住一个更进一步Ja NioSocketChannel。

(2)格式解构AbstractChannel(Channel parent)对脚并给也就是说字符串,说明了字符串的也就是说如下。

● id:每个Channel都时会被分配一个唯一的id。

● parent:也就是说最大值配置文件为null。

● unsafe:通过初始解构newUnsafe()原理举例来说解构一个Unsafe对脚,它的种类是AbstractNioByteChannel.NioByteUnsafe在表面上类。

● pipeline:是通过初始解构new DefaultChannelPipeline(this)新成立的举例来说。

(3)AbstractNIOChannel里被字符串的也就是说如下。

● ch:被字符串为Ja原生SocketChannel,即NioSocketChannel的newSocket()原理赶回的Ja NIO SocketChannel。

● readInterestOp:被字符串为SelectionKey.OP_READ。

● ch:被配置为非封闭,即初始解构ch.configureBlocking(false)原理。

(4)NioSocketChannel里被字符串的也就是说:config=new NioSocketChannelConfig(this,socket.socket())。

1.4 Unsafe也就是说的格式解构

上节我们直观地提过了,在举例来说解构NioSocketChannel的转换过程里,时会在父类AbstractChannel的在结构上原理里初始解构newUnsafe()原理来赚取一个Unsafe举例来说。那么Unsafe是怎么格式解构的呢?它的发挥作用是什么?

在举例来说解构NioSocketChannel的转换过程里,Unsafe就特别关键。Unsafe毕竟是对Ja里层Socket转换的封装,因此,它实际上是沟通Netty上层和Ja里层的重要桥梁。后面我们看一下Unsafe模块所缺少的原理。

从上述字符里可以显出,这些原理毕竟都是与Ja里层的相关Socket的转换相近似于的。

暂时赶回AbstractChannel的在结构上原理里,在这里初始解构了newUnsafe()原理赚取一个更进一步Unsafe对脚,而newUnsafe()原理在NioSocketChannel里被润色了,字符如下。

NioSocketChannel的newUnsafe()原理时会赶回一个NioSocketChannelUnsafe举例来说。从这里我们就可以相符,在举例来说解构的NioSocketChannel里的Unsafe也就是说毕竟是一个NioSocketChannelUnsafe的举例来说。

1.5 ChannelPipeline的格式解构

1.3节里我们量化了NioSocketChannel的都是格式解构转换过程,但是漏掉了一个关键的部分,即ChannelPipeline的格式解构。在Pipeline的注释说明了里所写道“Each channel has its own pipeline and it is created automatically when a new channel is created”。我们告诉他,在举例来说解构一个Channel时,这不都要举例来说解构一个ChannelPipeline。而我们确实在AbstractChannel的在结构上缓冲器里碰到了Pipeline也就是说被格式解构为DefaultChannelPipeline的举例来说。DefaultChannelPipeline在结构上缓冲器的字符如下。

DefaultChannelPipeline的在结构上缓冲器必需传到一个Channel,而这个Channel毕竟就是我们举例来说解构的NioSocketChannel对脚,DefaultChannelPipeline时会将这个NioSocketChannel对脚完好在Channel也就是说里。DefaultChannelPipeline里还有两个特殊的也就是说,即Head和Tail,这两个也就是说是双向双队列的脚和尾。毕竟在DefaultChannelPipeline里确保了一个以AbstractChannelHandlerContext为节点原素的双向双队列,这个双队列是Netty借助于Pipeline有助于的关键。关于DefaultChannelPipeline里的双向双队列及其所起的发挥作用,本节我们暂不请教,不足之处先花钱全面性量化。先以看HeadContext的让位分层,如下平面图标明。

TailContext的让位分层如下平面图标明。

我们可以碰到,双队列里Head是一个ChannelOutboundHandler,而Tail则是一个ChannelInboundHandler。接着看HeadContext的在结构上缓冲器的字符。

它初始解构了父类AbstractChannelHandlerContext的在结构上缓冲器,并传到给定inbound=false,outbound=true。而TailContext的在结构上缓冲器与HeadContext的相反,它初始解构了父类AbstractChannelHandlerContext的在结构上缓冲器,并传到给定inbound=true,outbound=false,即Head是一个OutBoundHandler,而Tail是一个InBoundHandler。关于这一特质,大家要需注意。不足之处量化到Netty的Pipeline时,时会不停用到inbound和outbound这两个也就是说。

1.6 EventLoop的格式解构

赶回最开始的ChatClient服务器字符里,我们在一开始就举例来说解构了一个NioEventLoopGroup对脚,因此就从它的在结构上缓冲器里EventLoop的格式解构转换过程。首先以来看NioEventLoopGroup的类让位分层,如下平面图标明。

NioEventLoop有几个重载的在结构上缓冲器,不过具体内容都没有很大的不同之处,最后都初始解构父类MultithreadEventLoopGroup的在结构上缓冲器,字符如下。

其里有语意的大都是,如果我们传到的内核天内nThreads是0,那么Netty时会另设配置文件的内核天内DEFAULT_EVENT_LOOP_THREADS,而这个配置文件的内核天内是怎么相符的呢?

毕竟很直观,在静态字符块里,首先以相符DEFAULT_EVENT_LOOP_THREADS的最大值。

Netty首先以从系统也就是说里赚取“io.netty.eventLoopThreads”的最大值,如果我们没有另设,就赶回配置文件最大值,即CPU核天内×2。赶回MultithreadEventLoopGroup在结构上缓冲器里时会暂时初始解构父类MultithreadEventExecutorGroup的在结构上缓冲器。

暂时搜索newChooser()原理看毕竟现逻辑上,说明了字符如下。

侧面字符主要传达的语意是:如果nThreads是2的平方,则用于PowerOfTwoEventExecutorChooser,否则用于GenericEventExecutorChooser。这两个Chooser都润色next()原理。next()原理的主要功能性就是将codice_目录循环系统偏转,如下平面图标明。

当目录移动到仍要一个位置时,先初始解构next()原理就时会将目录位置重新连到0,如下平面图标明。

这个指令集逻辑上毕竟很直观,就是每次让目录自增后与codice_尺寸取模:idx.getAndIncrement()%executors.length。但是就连一个非常直观的codice_目录指令集,Netty都帮我们花钱了优解构。因为在计算机里层,Price比%指令集效率更高。

量化到这里,我们早就非常正确MultithreadEventExecutorGroup里的执行逻辑上,直观阐释如下。

(1)成立一个形状为nThreads的SingleThreadEventExecutorcodice_。

(2)根据nThreads的形状,成立不同的Chooser,即如果nThreads是2的平方,则用于PowerOfTwoEventExecutorChooser,反之用于GenericEventExecutorChooser。不论用于哪个Chooser,它们的功能性都是一样的,即从childrencodice_里选一个合适的EventExecutor举例来说。

(3)初始解构newChild()原理格式解构childrencodice_。

根据侧面的字符,我们也能告诉他MultithreadEventExecutorGroup在表面上确保了一个EventExecutorcodice_,而Netty的EventLoopGroup的借助于有助于毕竟就建立在MultithreadEventExecutorGroup之上。每当Netty必需一个EventLoop时,都时会初始解构next()原理赚取一个可用的EventLoop。

侧面字符的仍要一部分是newChild()原理,这是一个抽脚原理,它的任务是举例来说解构EventLoop对脚。我们搜索一下它的字符,可以注意到,这个原理在NioEventLoopGroup类里有借助于,其具体内容如下。

毕竟逻辑上很直观,就是举例来说解构一个NioEventLoop对脚,然后赶回NioEventLoop对脚。

仍要阐释一下整个EventLoopGroup的格式解构转换过程。

(1)EventLoopGroup(毕竟是MultithreadEventExecutorGroup)在表面上确保一个种类为EventExecutor的childrencodice_,其形状是nThreads,这样就构成了一个内核出水口。

(2)我们在举例来说解构NioEventLoopGroup时,如果指明内核出水口形状,则nThreads就是指明的最大值,反之是CPU核天内×2。

(3)在MultithreadEventExecutorGroup里初始解构newChild()脚原理来格式解构childrencodice_。

(4)newChild()原理是在NioEventLoopGroup里借助于的,它赶回一个NioEventLoop举例来说。

(5)格式解构NioEventLoop对脚并给也就是说字符串,说明了字符串的也就是说如下。

● provider:就是在NioEventLoopGroup在结构上缓冲器里,初始解构SelectorProvider.provider()原理赚取的SelectorProvider对脚。

● selector:就是在NioEventLoop在结构上缓冲器里,初始解构provider.openSelector()原理赚取的Selector对脚。

1.7 将Channel登记到Selector

在1.3节的量化里,我们提过Channel时会在Bootstrap的initAndRegister()里同步进行格式解构,但是这个原理还时会将格式解构好的Channe登记到NioEventLoop的Selector里。每一次我们量化一下Channel登记的转换过程。

先以回顾一下AbstractBootstrap的initAndRegister()原理,字符如下。

当Channel格式解构后,紧接着时会初始解构group().register()原理来向Selector登记Channel。暂时搜索的话,时会注意到其初始解构双链如下平面图标明。

通过搜索初始解构双链,我们最后注意到在AbstractBootstrap的initAndRegister()原理里初始解构的是Unsafe的register()原理,每一次看一下AbstractChannel$AbstractUnsafe.register()原理的说明了借助于字符。

首先以,将EventLoop字符串给Channel的eventLoop也就是说,我们告诉他EventLoop对脚毕竟是通过MultithreadEventLoopGroup的next()原理赚取的,根据中间的量化,可以相符next()原理赶回的eventLoop对脚是NioEventLoop举例来说。register()原理接着初始解构了register0()原理,字符如下。

register0()原理又初始解构了AbstractNioChannel的doRegister()原理,字符如下。

碰到jaChannel()这个原理,我们在中间早就告诉他了,它赶回的是一个Ja NIO的SocketChannel对脚,这里我们将SocketChannel登记到与eventLoop联系的Selector上。

我们阐释一下Channel的登记转换过程,说明了如下。

(1)在AbstractBootstrap的initAndRegister()原理里,通过group().register(channel)初始解构MultithreadEventLoopGroup的register()原理。

(2)在MultithreadEventLoopGroup的register()原理里,初始解构next()原理赚取一个可用的SingleThreadEventLoop,然后初始解构它的register()原理。

(3)在SingleThreadEventLoop的register()原理里,初始解构channel.unsafe().register(this,promise)原理赚取Channel的unsafe()里层转换对脚,然后初始解构Unsafe的register()原理。

(4)在AbstractUnsafe的register()原理里,初始解构register0()原理登记Channel对脚。

(5)在AbstractUnsafe的register0()原理里,初始解构AbstractNioChannel的doRegister()原理。

(6)AbstractNioChannel的doRegister()原理通过jaChannel().register(eventLoop().selector,0,this)将Channel近似于的Ja NIO的SocketChannel登记到一个eventLoop的Selector里,并且将当前Channel作为Attachment与SocketChannel联系。

总的来说,Channel的登记转换过程所花钱的工作就是将Channel与近似于的EventLoop同步进行联系。因此,在Netty里,每个Channel都时会联系一个特定的EventLoop,并且这个Channel里的所有I/O转换都是在这个EventLoop里执行的;当联系好Channel和EventLoop后,时会暂时初始解构里层Ja NIO的SocketChannel对脚的register()原理,将里层Ja NIO的SocketChannel登记到指明的Selector里。通过这反应过程,就收尾了Netty对Channel的登记转换过程。

1.8 Handler的去掉转换过程

Netty有一个强大和灵活之处就是基于Pipeline的可选Handler有助于。基于此,我们可以像去掉插件一样自由组合各种各样的Handler来收尾业务逻辑上。例如我们必需执行HTTP天内据库,那么就可以在Pipeline前去掉一个针对HTTP编解码器的Handler,然后去掉我们自己的业务逻辑上的Handler,这样互联上的匹配就像通过一个水管一样,从不同的Handler里流过并同步进行编解码器,最后开到我们可选的Handler里。

说到这里,有些小伙伴认同时会好奇,既然这个Pipeline有助于这么强大,那么它是怎么借助于的呢?在此我们不同步进行详细请教,而是从直观的具体内容入手,先以体验一下可选的Handler是如何及何时去掉到ChannelPipeline里的。我们看一下服务器字符片断。

这个字符片断就借助于了Handler的去掉功能性。我们碰到,Bootstrap的handler()原理接收一个ChannelHandler,而我们传到的给定是一个授意生于抽脚类ChannelInitializer的电子邮件类,它也借助于了ChannelHandler模块。我们来看ChannelInitializer类里到底有什么神州,字符如下。

ChannelInitializer是一个抽脚类,它有一个抽脚的initChannel()原理,我们碰到的电子邮件类正是借助于了这个原理,并在这个原理里去掉了可选的Handler。那么initChannel()原理是在哪里被初始解构的呢?毕竟是在ChannelInitializer的channelRegistered()原理里。

每一次关切一下channelRegistered()原理。我们从侧面的字符里可以碰到,在channelRegistered()原理里,时会初始解构initChannel()原理,将可选的Handler去掉到ChannelPipeline里,然后初始解构ctx.pipeline().remove(this)原理将自己从ChannelPipeline里删掉。

一开始,ChannelPipeline里只有三个Handler,分别是Head、Tail和我们去掉的ChannelInitializer,如下平面图标明。

接着初始解构initChannel()原理,去掉可选的Handler,如下平面图标明。

仍要将ChannelInitializer删掉,如下平面图标明。

量化到这里,我们早就直观了解了可选的Handler是如何去掉到ChannelPipeline里的,之后的前言我们先同步进行全面性的探讨。

早生白发的人怎么治疗好
产后束身
五官面部整形
江中多维元素片
波比宁治疗偏头痛效果怎么样
标签:
友情链接: