netty服务端处理请求联合pipeline源码分析


本篇内容主要讲解“netty服务端处理请求联合pipeline源码分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“netty服务端处理请求联合pipeline源码分析”吧!在客户端接入的时候, NioMessageUnsaferead方法中pipeline.fireChannelRead(readBuf.get(i))为什么会调用到ServerBootstrap的内部类ServerBootstrapAcceptor中的channelRead()方法。客户端handler是什么时候被添加的?先分析第一个问题。回到netty处理客户端请求分析_1中服务端接收到accpet事件后,进行读取的方法NioMessageUnsafe.read()重点看pipeline.fireChannelRead(readBuf.get(i))首先, 这里pipeline是服务端channelpipeline, 也就是NioServerSocketChannelpipeline我们学习过pipeline之后, 对这种写法并不陌生, 就是传递channelRead事件, 这里通过传递channelRead事件走到了ServerBootstrapAcceptorchannelRead()方法, 说明在这步之前, ServerBootstrapAcceptor作为一个handler添加到了服务端channelpipeline中, 那么这个handler什么时候添加的呢?我们回顾下第一章, 初始化NioServerSocketChannel的时候, 调用了ServerBootstrap的init方法 回顾下ServerBootstrap.init的调用链路:ServerBootstrap.bind(8899) —> AbstractBootstrap.doBind(final SocketAddress localAddress) —> AbstractBootstrap.initAndRegister() —> ServerBootstrap.init(Channel channel)我们重点关注第8步, 添加服务端channel, 这里的pipeline, 是服务服务端channelpipeline, 也就是NioServerSocketChannel绑定的pipeline, 这里添加了一个ChannelInitializer类型的handler我们看到其继承了ChannelInboundHandlerAdapter, 说明是一个inbound类型的handler这里我们可能会想到, 添加完handler会执行handlerAdded, 然后在handlerAdded方法中做了添加ServerBootstrapAcceptor这个handler但是, 实际上并不是这样的, 当程序执行到这里, 并没有马上执行handlerAdded, 我们紧跟addLast方法最后执行到DefualtChannelPipeline.addLast(EventExecutorGroup group, String name, ChannelHandler handler)首先完成了handler的添加, 但是并没有马上执行回调这里我们重点关注if (!registered)这个条件判断, 其实在注册完成, registered会变成true, 但是走到这一步的时候NioServerSockeChannel并没有完成注册(可以回顾第一章看注册在哪一步), 所以会进到if里并返回自身DefualtChannelPipeline.callHandlerCallbackLater(AbstractChannelHandlerContext ctx, boolean added)因我们调用这个方法的时候added传的true, 所以PendingHandlerCallback task赋值为new PendingHandlerAddedTask(ctx)PendingHandlerAddedTask这个类, 我们从名字可以看出, 这是一个handler添加的延迟任务, 用于执行handler延迟添加的操作, 同样也对应一个名字为PendingHandlerRemovedTask的类, 用于执行延迟删除handler的操作, 这两个类都继承抽象类PendingHandlerCallback进入super(ctx)在父类中, 保存了要添加的context, 也就是ChannelInitializer类型的包装类这表示获取第一个PendingHandlerCallback的任务, 其实PendingHandlerCallback是一个单向链表, 自身维护一个PendingHandlerCallback类型的next, 指向下一个任务, 在DefaultChannelPipeline这个类中, 定义了个PendingHandlerCallback类型的引用pendingHandlerCallbackHead, 用来指向延迟回调任务的中的第一个任务。之后判断这个任务是为空, 如果是第一次添加handler, 那么这里就是空, 所以将第一个任务赋值为我们刚创建的添加任务。如果不是第一次添加handler, 则将我们新创建的任务添加到链表的尾部, 因为这里我们是第一次添加, 所以第一个回调任务就指向了我们创建的添加handler的任务。完成这一系列操作之后, addLast方法返归, 此时并没有完成添加操作。而什么时候完成添加操作的呢?回到在服务端channel注册时候的会走到AbstractChannel.register0方法 回顾下AbstractChannel.register0的调用链路:ServerBootstrap.bind(8899) —> AbstractBootstrap.doBind(final SocketAddress localAddress) —> AbstractBootstrap.initAndRegister() —> config().group().register(channel) —> SingleThreadEventLoop.register(final ChannelPromise promise) —> AbstractChannel.register(EventLoop eventLoop, final ChannelPromise promise) —> AbstractChannel.register0(ChannelPromise promise)重点关注第二步pipeline.invokeHandlerAddedIfNeeded(), 这里已经通过doRegister()方法完成了实际的注册, 我们跟到该方法中这里会判断是否第一次注册, 这里返回true, 然后会执行callHandlerAddedForAllHandlers()方法, 我们跟进去这里拿到第一个延迟执行handler添加的task其实就是我们之前剖析过的, 延迟执行handler添加的task, 就是PendingHandlerAddedTask对象在while循环中, 通过执行execute()方法将handler添加再进入callHandlerAdded0方法终于在这里, 我们看到了执行回调的方法我们继续看第8步添加服务端handler因为这里的handlerChannelInitializer, 所以完成添加之后会调用ChannelInitializerhandlerAdded方法跟到handlerAdded方法因为执行到这步服务端channel已经完成注册, 所以会执行到initChannel方法我们关注initChannel这个方法, 这个方法是在ChannelInitializer的匿名内部来实现的, 这里我们注意, 在initChannel方法执行完毕之后会调用remove(ctx)删除当前节点这里首先添加用户自定义的handler, 这里如果用户没有定义, 则添加不成功, 然后, 会调用addLastServerBootstrapAcceptor这个handler添加了进去, 同样这个handler也继承了ChannelInboundHandlerAdapter, 在这个handler中, 重写了channelRead方法, 所以, 这就是第一个问题的答案紧接着我们看第二个问题:客户端handler是什么时候被添加的?这里真相可以大白了, 服务端再创建完客户端channel之后, 将新创建的NioSocketChannel作为参数触发channelRead事件(可以回顾NioMessageUnsafe.read方法, 代码这里就不贴了), 所以这里的参数msg就是NioSocketChannel拿到channel时候再将客户端的handler添加进去, 我们回顾客户端handler的添加过程:和服务端channel的逻辑一样, 首先会添加ChannelInitializer这个handler但是没有注册所以没有执行添加handler的回调, 将任务保存到一个延迟回调的task中等客户端channel注册完毕, 会将执行添加handler的回调, 也就是handlerAdded方法, 在回调中执行initChannel方法将客户端handler添加进去, 然后删除ChannelInitializer这个handler因为在服务端channel中这块逻辑已经进行了详细的剖析, 所以这边就不在赘述, 同学们可以自己跟进去走一遍流程这里注意, 因为每创建一个NioSoeketChannel都会调用服务端免费云主机域名ServerBootstrapAcceptorchannelRead方法, 所以这里会将每一个NioSocketChannelhandler进行添加。到此,相信大家对“netty服务端处理请求联合pipeline源码分析”有了更深的了解,不妨来实际操作一番吧!这里是百云主机网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

相关推荐: 怎么使用PHP跳转到另一个控制器

这篇文章主要介绍了怎么使用PHP跳转到另一个控制器的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么使用PHP跳转到另一个控制器文章都会有所收获,下面我们一起来看看吧。 首先,我们需要通过PHP中的header()函数来实现跳转。…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

Like (0)
Donate 微信扫一扫 微信扫一扫
Previous 07/05 19:56
Next 07/05 19:56

相关推荐