Netty中的上下游处理器是如何工作的?

4

我刚接触 Netty,对其中的handlers流程并不了解。我想知道UpstreamDownstream处理器之间的区别。

  • 为什么我们不能像在upstream处理器中那样在downstream处理器中拦截消息?
  • downstream和upstream在正常情况下的意思是否相同?
2个回答

8
区别在于其中一个处理传入(上行)流,另一个处理传出(下行)流。查看ChannelPipeline的JavaDoc后,事件/消息流变得更加清晰。
我还应该注意,只有IO-Thread才会触发上行事件/消息,因此如果您每个ChannelPipeline使用一个新的ChannelUpstreamHandler,则无需在其中同步字段访问。 下行事件可以由任何线程触发,因此需要同步对字段的访问。

谢谢您的回复...但我不明白的是,在Jboss Netty网站提供的telnet应用程序中,它使用上游处理程序来打印从服务器返回的消息...但为什么他们不使用下游处理程序呢...?您能否举一个下游处理程序的例子... - Pradeep
1
就像我之前所说的,上游是用于传入数据的,这在示例中也是如此。下游事件的一个例子是编码器需要将您编写的对象编码为ChannelBuffer。有关示例,请参见https://github.com/netty/netty/blob/3.2/src/main/java/org/jboss/netty/handler/codec/oneone/OneToOneEncoder.java。 - Norman Maurer
非常抱歉再次打扰您..您能否解释一下IO线程是什么意思?例如,在Telnet应用程序中,客户端上游处理程序是如何被触发的呢?我想这就是我真正不理解的地方... - Pradeep
1
一旦接收到缓冲区,它将触发一个事件,该事件将发送到ChannelPipeline。 ChannelPipeline将使用其ChannelUpstreamHandler实例处理它。 - Norman Maurer
1
它不会像输出那样显示。我猜你认为它是从底部到顶部的,但事实并非如此。当你更仔细地观察时,你会注意到上游是由Socket.read(..)触发的,这是传入的。 - Norman Maurer
显示剩余4条评论

4

理论信息

我认为这些想法是从网络堆栈中派生出来的。Netty的“handler-pipeline”类比类似于OSI网络层堆栈。看一下OSI网络层的样子:

enter image description here

把每个处理器(handler)看作一个“层”,整个管道(pipeline)看作一个“网络堆栈”,物理链接看作“IO源”,用户看作“应用逻辑处理器”。使用相同的管道(堆栈),我们需要执行两个功能:

  1. 传输数据(当“应用逻辑处理程序”想要通过“IO源”执行某些操作时,向下发送数据)。
  2. 接收数据(当“IO源”具有某些事件时(可能是应用逻辑处理程序感兴趣的事件),向上发送数据)。

因此,基本上相同的管道必须执行两个不同的操作(接收消息并将消息发送回去)。


实际例子

让我们考虑一个具体的例子(具有身份验证和加密的服务器),由3个处理器组成了一个管道:

Example Netty pipeline with 3 handlers

让我们来看一下每个接收消息的处理器的职责

  1. 加密处理程序->需要从“IO源”接收UpstreamEvent,从上述流中的“应用程序处理程序”或“Auth Handler”接收DownstreamEvent。
  2. Auth handler - >仅需要从“Encryption handler”接收UpstreamEvent。
  3. 应用程序处理程序->仅需要从“Auth Handler”接收UpstreamEvent。

因此,从逻辑上讲,每个处理器都必须实现以下内容:

  1. 加密处理程序-> ChannelUpstreamHandler和ChannelDownstreamHandler
  2. Auth handler - > ChannelUpstreamHandler
  3. 应用程序处理程序 - > ChannelUpstreamHandler

因此,如果您有一个具有上述3个处理程序的ChannelPipeline,则需要执行以下操作:

  • 对于传入的消息:'IO source'(0)发起UpstreamEvent,Netty将把UpstreamEvent转发到(1)、(2)、(3),因为它们都实现了ChannelUpstreamHandler
  • 当'Application handler'(3) / 'Auth Handler'(2)想要向客户端发送状态消息时,它将通过write调用(创建DownstreamEvent)来发起。Netty将把DownstreamEvent转发到(1)(只有一个,在(3)之前,并且实现了ChannelDownstreamHandler)。

所以在具有处理程序的管道中,当创建UpstreamEvent时(由'IO源'创建),Netty将按顺序调用从1到n的所有处理程序,这些处理程序都实现了ChannelUpstreamHandler(在上面的示例中,n=3)。当创建DownstreamEvent时(由用户应用程序代码创建),Netty将按顺序调用从n1的所有处理程序,这些处理程序都实现了ChannelDownstreamHandler

由于一个类可以实现两个接口,一个处理程序既可以是ChannelUpstreamHandler,也可以是ChannelDownstreamHandler。请注意,所有UpstreamEvent都是由'IO源'创建的,而所有DownstreamEvent都是由用户应用逻辑创建的。


通道事件示例

UpstreamEvent的示例:

  1. 接收到消息
  2. 打开通道
  3. 关闭通道
  4. 'IO源'引发异常
  5. 'IO源'完成写操作
  6. 通道断开连接
  7. ...

DownstreamEvent的示例:

  1. 向通道写入消息
  2. 绑定端口
  3. 连接到服务器地址
  4. ...

希望这能帮助您回答“为什么处理程序需要两种行为(上游和下游)”、“Netty如何通过DownstreamUpstream解决发送和接收问题”以及“我们如何在现实世界的应用程序中真正使用这些构造”。

您的答案到此结束,如果需要额外内容,请继续阅读以下内容。


关于上述介绍的处理程序

让我们看一下上述介绍的每个处理程序在转发消息方面的责任:

  1. 应用程序处理程序 --> 需要将消息转发到前面的层(应该隐式或显式地调用 ctx.sendDownstream(e))。
  2. 认证处理程序 --> 需要将消息转发到前面的层(对于认证失败),并将消息转发到后续层(对于认证成功)。(应该隐式或显式地调用ctx.sendDownstream(e)ctx.sendUpstream(e))。
  3. 加密处理程序 --> 需要将消息转发到前面和后续层(应该隐式或显式地调用ctx.sendDownstream(e)ctx.sendUpstream(e))。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接