当前位置: 首页 > 网络应用技术

Netty源代码3通道Pipeline和ChannelHandler

时间:2023-03-08 17:50:26 网络应用技术

  欢迎大家注意github.com/hsfxuebao。我希望这对每个人都会有所帮助。如果您认为有可能

  Netty的通道滤波器实现原理与Servlet和Filter的服务机理一致。ChannelPipeline保留I/O事件interceptor ChannelHandler的链接列表,该列表由ChannelHandler由I/O事件拦截和处理。它不需要修改现有的频道Handler即可获得支持以修改和扩展。

  下图显示了特定事件传播流程图:

  首先,关系:

  再次和ChannelPipeleline。此,每个频道HandlerContext都与ChannelHandler关联(此ChannelHandlerContext只是ChannelHandler的上下文,用于保存上下文环境并与ChannelHandler的前后通信进行通信),如下所示:下面:下面:

  频道概念与Java.nio.Channel的概念一致,该通道用于连接到IO设备(套接字,文件等)。网络地址等。

  频道IO类型的主要类型有两种:非遮挡IO(NIO)和阻止IO(OIO)。

  数据传输有两种类型:根据事件消息(消息)和字节传输(字节)。

  还有两种适用的平方类型:serversocket和客户端(套接字)。还有一些根据传输协议制定的渠道,例如:UDT,SCTP等。

  Netty根据类型设计了相应的类。底层是一个抽象类,然后根据IO类型,数据传输类型和适用的Square类型实现。类图可以看出一眼,如下图所示:

  ChannelRegister

  从评论中,您可以看到它被绑定到它时被调用。

  无论是服务器还是客户端,当它被绑定时,它最终被称为此方法(在使用时将其调用服务器,并且在其为时调用客户端)。

  该方法定义如下:

  继续跟踪将定位到该方法。

  也可以从上面的代码中看到。调用呼叫后,将调用以确定当前链接是否激活。如果被激活,将调用呼叫方法。

  目前,客户端和服务器都没有被激活,因此目前服务器和客户端都不会调用该方法。

  通道状态

  从启动器的接口开始,调低该方法:

  该方法将调用该方法,在该方法中,将通过该方法执行的任务。

  该方法将被调低;该方法,传输机制最终将调用该方法。该方法主要做两件事:

  换句话说,当连接新客户时,它将成为活动状态。

  ChannelInactive状态

  该方法将在两个地方调用:和。

  在致电之前,请确认状态来自--->。

  Channelunnegistered状态

  提起注册时应调用该方法。

  ChannelHandler类似于服务的过滤器,该滤波器负责拦截和处理I/O事件或I/O操作。它可以有选择地拦截和处理感兴趣的事件。基于ChannelHandler接口,用户可以轻松自定义业务逻辑,例如打印日志,统一包装异常信息,性能统计信息和消息编解码器。

  ChannelHandler支持注释,目前有两种评论类型。

  :添加到时间通话。

  处理I/O事件或拦截I/O操作,并将其转发到下一个处理程序。它没有提供许多方法,但通常是其儿童类型之一:

  :当频道已注册其estentloop并在可以处理I/O时可以调用。活动状态,不再连接到远程节点。:从频道读取数据时,它被称为。:当频道上的读取操作完成时,当从频道读取所有可读字节时,都会调用。方法将被调用。

  退出操作和数据将由ChannelOutBoundHandler处理。它的方法将被调用并调用。

  强大的功能是延迟按需操作或事件,这允许一些复杂的方法处理请求。例如,如果暂停远程节点的写入,则可以推迟刷新操作并稍后继续。

  :当频道连接到节点时调用请求时。:当请求与远程节点断开请求时调用请求时。:当请求从其eventloop取消时调用请求时。当调用数据时,请从通道morecall中阅读更多信息。:通过频道请求数据将数据写入远程节点时。:当请求从频道到远程节点调用请求时,请求。

  ChannelPromise和Channeneldure

  这意味着在Netty的所有I/O操作中,介质和不同步骤的I/O操作的结果都是异步的。I/O的呼叫将直接返回。您可以获取I/O操作的结果或状态信息。

  当I/O操作启动时,将创建一个新对象。新对象未完成,因为I/O操作尚未完成,它既没有成功也没有取消。

  如果I/O操作已成功完成(失败或取消),则该对象将被标记为已完成,其中包含更具体的信息,例如失败原因。

  请注意,即使失败和取消已经完成。

  是的,子界面定义了一些写作方法,例如和谐,因此不会改变。

  优先使用AddListener(GeneicFutureListener)而不是等待())

  当它是I/O操作并具有任何关注任务时,建议获取通知,而不是没有

  正确和非烧烤。它将在中间添加特定于中间,然后当I/O操作相关的未来完成时,I/O线程将通知监视器。

  它将受益最佳的性能和资源使用,因为它根本不会阻止它。它不会导致死锁。

  两个适配器类的基本实施提供了和平。他们继承了共同的父接口方法并扩展了抽象类。

  它还提供实用方法。

  如果标记其相应的实现,则此方法将返回,表明它可以添加到多个。

  中国提供的方法称之为与之相关的等效方法,以便将事件转发到中间。

  Netty提供了一些处理程序,开发人员可以选择继承一些功能

  编辑:bytetomessagecoder ....

  半包装处理:DelimiterBasedFramedeCoder,fixellengthframedecoder ...

  可以通过接口找到ChannelPipeline具有两个主要功能:

  继承图如下:

  在我们已经知道渠道初始化的基本过程之前,让我们在下面对其进行审查。以下代码为AbstractCtchanel构造函数:

  而且,他们都实现了ChannelHandlerContext接口,因此可以说头部和尾巴是通道手和频道HandlerContext。

  AbstractChannel具有一个管道字段,可以将其作为DefaultChannelPipeline的实例初始化。首先输入DefaultChannelPipeline构造函数::

  在DefaultChannelPipeline构造函数中,将与之关联的通道保存到字段通道中。然后实例化了两个ChannelHandLercontext:一个是HeadScontext实例头,另一个是TailContext实例尾部。方式链接列表。

  特别是,启动示意图中的头部和尾巴不包括ChannelHandler,因为HeadContext和TailContext继承了AbstractChanlHandlContext也实现了ChannelHandler接口,因此它们具有上下文和处理程序的双重特点。

  Netty中的通信事件可以分为两种类型:入站事件和出站事件。以下是Netty官方网站的这两个事件的解释。再次查看图片:

  从上图可以看出,入站事件的方向和出站事件是不同的:

  出站类似于活动触发器(事件启动请求);

  出站事件都是所有请求事件,也就是说,请求发生某些事情,然后通知出站事件。出站事件的传播方向是尾巴 - > customcontext-> head。

  ChannelOutBoundHandler方法是:

  让我们以连接事件为例,以分析出站事件的通信机制。

  首先,当用户调用Bootstrap的Connect()方法时,将触发连接请求事件。此呼叫将触发呼叫链如下:

  继续跟踪,我们发现AbstractCtChanel's Connect()的Connect()实际上调用了DefaultChannelPipeline ::的连接()方法

  可以看出,当出站事件(此处是连接事件)传递给Pipeline..connect()时,实际上调用了Abstractctctctctctctchanlhandlcontext的连接()方法::):

  findContextOutBound(mask_connect)方法,如名称所建议,然后return.findContextOutBound(mask_connect)方法代码被实现如下:

  当我们找到出站上下文时,请调用其InvokeConnect()方法。此方法将调用与上下文关联的Connected ChannelHandler关联的上下文连接()方法:

  如果用户未重写ChannelHandler的Connect()方法,则称为ChannelOutBoundHandlerAdapter的Connect()称为::

  我们看到ChannelOutBoundHandlerAdlerAdapter的连接()仅称为ctx.connect(),然后返回了此调用:在此周期中,直到连接事件的两个链接事件的头节点传递给DefaultChannelPipeline(即,在头上。为什么要通过?回想一下,头部实现ChannelOutBoundHandler。由于头部本身不仅是ChannelHandlerContext,而且还实现了ChannelOutBoundHandler接口。因此,当连接()消息传递给头部时,该消息将转移到相应的ChannelHandler。Headler()方法返回头部本身:

  因此,在Head.head的Connect()事件处理逻辑中处理了Final()事件如下:

  此时,整个连接()请求事件已经结束。下图描述了整个连接()请求事件的处理过程:

  入站类似于事件调用(响应请求),

  入站的特征是它的传播方向是头 - > CustomContext->尾巴。

  ChannelInboundhandler方法是:

  请注意,如果我们捕获事件并希望继续通过此事件,我们需要调用与上下文相对应的相应通信方法firexxx。

  例如,以下示例代码:MyInboundHandler收到了一个频道事件。处理后,如果要继续事件,则需要调用ctx.firechannelactive()方法。

  入站事件类似于出站事件的处理过程,但是通信的方向不同。事件是通知事件,也就是说,发生了一些事情,然后通过入站事件通知。渠道或IO事件。

  入站的特征是它的传播方向是头 - > CustomContext->尾巴。

  上面我们分析了Connect()的出站事件,然后分析了Connect()事件后的入站事件将发生的事情,最后发现了出站和入站事件之间的连接。当出站()扩散到Unsafe时,IT实际上是在AbstractNiounsafe ::的Connect()方法中处理的

  在AbstractNiounsafe的Connect()方法中,首先调用用于实际套接字连接的DoconNect()方法。连接连接时

  我们看到,在ExhiLlConnectPromise()中,通道激活的通道激活(即插座连接)是通过调用pipeline()。在调用pipeline.firexxx时发送的,这是入站事件的起点。,当pipeline()。Firechannelactive(),生成了通道的入站事件。从这里开始,我们将看到此入站事件如何传播?

  果然,在firechannelactive()方法中,head.invokechannelactive()被调用,所以管道中的入站事件的起点是头。那么您在head.invokechannelactive()中做了什么?

  上面的代码应熟悉。回到出站事件的传输过程(例如Connect()事件),我们也有类似的操作:

  此方法与出站的相应方法完全相同(例如:InvokeConnect())。像出站一样,如果用户未重写channelActive()方法,则调用ChannelInboundlerAdapter:::::::::)的ChannelActive()方法:

  ) - > nextContext.firechannelactive()。以相同的方式,尾部本身不仅实现了ChannelInboundHandler接口,还实现了ChannelHandlerContext接口。因此,当消息()消息传递给尾部时,该消息将传输到相应的channelhandler,而尾部的处理程序()返回尾巴。

  tailContext的ChannelActive()方法是空的。如果您自己查看TailContext的入站处理方法,您会发现它们的实现是空的。,默认情况下不处理它。下面的图描述了入站事件的传输过程:

  1.出站事件是请求事件(Connect()初始请求,并最终通过不安全处理此请求)。

  2.出站事件的发起者是频道。

  3.出站事件的处理器不安全。

  4.管道中出站事件的方向是尾巴 - >头部。这是指contexthandler

  5.在ChannelHandler中处理事件时,如果此处理程序不是最后一个处理程序,则需要调用CTX方法(例如:CTX.Connect()方法)继续事件。如果您不这样做,该事件的传播将事先终止。

  6.出站事件流:context.out_evt() - > connect.findContextOutBound() - > nextContext.invokeout_evt() - > NextContext.out_evt()

  1.入站事件是通知事件。准备好的东西时,会通知上层。

  2.入站事件发起者不安全。

  3.入站事件的处理器是通道。如果用户不实现自定义处理方法,则入站事件的默认处理器是tailContext,其处理方法是空的实现。

  4.入站事件是管道中的尾巴。

  5.在ChannelHandler中处理该事件时,如果此处理程序不是最后一个处理程序,则需要致电ctx.firein_evt()ctx.firechannelactive()方法)继续事件。如果您不这样做此事件将提前终止。

  上下文和处理程序之间的直接通话关系也很容易混淆,因此在此处阅读源代码时,我们需要特别注意。

  它代表和谐之间的关联,每当将其添加到中间时,它将被创建。

  主要功能是管理IT与其他相同其他之间的交互作用。

  有很多方法,其中一些方法也存在于上部,但是有一个重要的区别。

  如果呼叫方法和上述方法将沿着(从开始或结束开始)传播。当上面调用相同的方法时,它将从当前关联开始,并且仅将其传输到this.event中的下一个。

  这可以减少。呼叫费用。

  上图显示了Channel Pipeline ChannelHandler和ChannelHandlerContext之间的关系。

  Netty学习和源代码分析GitHub地址

  从进入到熟练视频教程(B)的Netty

  Netty权威指南第二版

  ChannelPipeline和ChannelHandler

  Netty的ChannelPipeline和ChannelHandler

  原始:https://juejin.cn/post/7097178349037944839