Netty-ChannelHandler-ChannelPipeline,java工作流面试题

本文介绍了Netty中的ChannelHandler,包括ChannelInboundHandler和ChannelOutboundHandler,详细阐述了它们各自处理的事件及接口方法。同时,讨论了ChannelPipeline的管理,如添加、删除和替换ChannelHandler,以及如何触发和传播事件。此外,提到了资源管理和泄漏检测的配置选项。
摘要由CSDN通过智能技术生成

| handlerAdded | 当把ChannelHandler添加到ChannelPipeline中时被调用 |

| handlerRemoved | 当从ChannelHandler在ChannelPipeline移除时调用 |

| exceptionCaught | 当处理过程中在ChannelPipeline中有错误产生时被调用 |

Netty中定义了下面两个重要的ChannelHandler接口:

  1. ChannelInboundHandler——处理入站数据以及各种状态变化

  2. CHannelOutboundHandler——处理出站数据并且允许拦截所有的操作

ChanneInboundHandler接口

| 类型 | 描述 |

| — | — |

| channelRegistered | 当Channel已经注册到它的EventLoop并且能够处理I/O时被调用 |

| channelUnregistered | 当Channel从它的EventLoop注销并且无法处理任何I/O时被调用 |

| channelActive | 当Channel处于活动状态时被调用;Channel已经连接/绑定并且已经就绪 |

| channelInactive | 当Channel离开活动状态并且不再连接它的远程节点时被调用 |

| channelReadComplete | 当Channel的一个读操作完成时被调用 |

| channelRead | 当从Channel读取数据时被调用 |

| channelWritabilityChanged | 当Channel的可写状态发生改变时被调用。用户可以确保写操作不会完成的太快(以避免发生OutOfMemoryError)或者可以在Channel变为再次可写时恢复写入。Channel的isWriteable()方法可以来检测Channel的可写性。与可写性相关的阀值可以通过Channel.config().setWriteHighWaterMark()和Channel.config().setWriteLowWaterMark()方法来设置 |

| userEventTriggered | 当ChannelInboundHandler.fireUserEventTriggered()方法被调用时被调用。 |

当某个ChannelInboundHandler的实现重写channelRead()方法时,它将负责显示地释放与池化的ByteBuf实例相关的内存。ReferenceCountUtil.release()

Netty会使用WARN级别的日志消息记录未释放的资源,但是以这种方式管理资源可能非常繁琐,Netty采用SimpleChannelInboundHandler来简化这种操作。

ChannelOutboundHandler接口

出站操作和数据将由ChannelOutboundHandler处理。它的方法将被Channel、ChannelPipeline以及ChannelHandlerContext调用。

ChannelOutboundHandler可以按需推迟操作或者事件。

| 类型 | 描述 |

| — | — |

| bind(ChannelHandlerContext, SockertAddress, ChannelPromise) | 当请求将Channel绑定到本地地址时被调用 |

| connect(ChannelHandlerContext, SocketAddress, SockertAddress, ChannelPromise) | 当请求将Channel连接到远程节点时被调用 |

| disconnect(ChannelHandlerContext, ChannelPromise) | 当请求将Channel从远程节点断开时被调用 |

| close(ChannelHandlerContext, ChannelPromise) | 当请求关闭Channel时被调用 |

| deregister(ChannelHandlerContext, ChannelPromise) | 当请求将Channel丛它的EventLoop注销时被调用 |

| read(ChannelHandlerContext) | 当请求从Channel读取更多的数据时被调用 |

| flush(ChannelHandlerContext) | 当请求通过Channel将入队数据冲刷到远程节点时被调用 |

| write(ChannelHandlerContext, Object, ChannelPromise) | 当请求通过Channel将数据写到远程节点时被调用 |

ChannelOutboundHandler中的大部分方法都需要一个ChannelPromise参数,方便在操作完成时获取通知。ChannelPromise时ChannelFuture的一个子类,定义了一些可写方法,如setSuccess()和setFailure()方法

ChannelHandler适配器

ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter两个适配器分别提供了ChannelInboundHandler和ChannelOutboundHandler的基本实现。通过扩展抽象类ChannelHandlerAdapter,它们获得了它们共同的超接口ChannelHandler的方法。

ChannelHandlerAdapter提供了isSharable(),如果其对应的实现被注解标注为Sharable,这方法将返回true,表示它可以被添加到多个ChannelPipeline。

ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter中的方法体调用了其相关联的ChannelHandlerContext上的等效方法,从而将事件转发到了ChannelPipeline中的下一个ChannelHandler中。

资源管理

Netty目前定义了4种泄露检测级别:

| 级别 | 描述 |

| — | — |

| DISABLED | 禁用泄漏检测。只有在详尽的测试之后才应设置为这值 |

| SIMPLE | 使用1%的默认采样率检测并报告任何发现的泄漏。这是默认级别,适合绝大部分情况 |

| ADVANCED | 使用默认的采样率,报告所发现的任何的泄漏以及对应的消息被访问的位置 |

| PARANOID | 类似于ADVANCED,但是其将会对每次(对消息的)访问都进行采样。会对性能有很大影响,只能在调试阶段使用 |

java -Dio.netty.leakDetectionLevel=ADVANCED

如果一个消息被消费或者丢弃了,并且没有传递给ChannelPipeline中的下一个ChannelOutboundHandler,那么用户就有责任调用ReferenceCountUtil.release()。如果消息到达了实际的传输层,那么当它被写入时或者Channel关闭时,都将被自动释放。

ChannelPipeline接口


每一个新创建的Channel都将会被分配一个新的ChannelPipeline。这项关联是永久性的;Channel既不能附加另外一个ChannelPipeline,也不能分离当前的。

根据事件的起源,事件将会被ChannelInboundHandler或者ChannelOutboundHandler处理。随后,会调用ChannelHandlerContext实现,它将被转发给同一超类型的下一个ChannelHandler。

ChannelHandlerContext使ChannelHandler能够和它的ChannelPipeline以及其他的ChannelHandler交互。ChannelHandler可以通知其所属的ChannelPipeline中的下一个ChannelHandler,甚至可以动态修改它所属的ChannelPipeline。

在ChannelPipeline传播事件时,它会测试ChannelPipeline中的下一个ChannelHandler的类型是否和事件的运动方向相匹配。如果不匹配,ChannelPipeline将跳过该ChannelHandler并前进到下一个,直到它找到和该事件所期望的方向相匹配的为止。(ChannelHandler可以同时实现ChannelInboundHandler和ChannelOutboundHandler接口

修改ChannelPipeline

ChannelHandler可以通过添加、删除或者替换其他的ChannelHandler来实时地修改ChannelPipeline的布局。

| 名称 | 描述 |

| — | — |

| addFirst(),addBefore(),addAfter(),addLast() | 将一个ChannelHandler添加到ChannelPipeline |

| remove() | 将一个ChannelHandler从ChannelPipeline中移除 |

| replace() | 将ChannelPipeline中的一个ChannelHandler替换为另一个ChannelHandler |

| get() | 通过类型或者名称返回ChannelHandler |

| context() | 返回和ChannelHandler绑定的ChannelHandlerContext |

| names() | 返回ChannelPipeline中所有的ChannelHandle的名称 |

触发事件

ChannelPipeline的API公开了用于调用入站和出站操作的附加方法,用于通知ChannelInboundHandler在ChannelPipeline中所发生的事件。

| 名称 | 描述 |

| — | — |

| fireChannelRegistered | 调用ChannelPipeline中下一个ChannelInboundHandler的channelRegistered(ChannelHandlerContext)方法 |

| fireChannelUnregistered | 调用ChannelPipeline中下一个ChannelInboundHandler的channelUnregistered(ChannelHandlerContext)方法 |

| fireChannelA

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

ctive | 调用ChannelPipeline中下一个ChannelInboundHandler的channelActive(ChannelHandlerContext) |

| fireChannelInActive | 调用ChannelPipeline中下一个ChannelInboundHandler的channelInactive(ChannelHandlerContext)方法 |

| fireExceptionCaught | 调用ChannelPipeline中下一个ChannelInboundHandler的exceptionCaught(ChannelHandlertext, Throwable)方法 |

| fireUserEventTriggerd | 调用ChannelPipeline中下一个ChannelInboundHandler的userEventTriggered(ChannelHandlertext, Object)方法 |

| fireChannelRead | 调用ChannelPipeline中下一个ChannelInboundHandler的channelRead(ChannelHandlertext, Object msg)方法 |

| fireChannelReadComplete | 调用ChannelPipeline中下一个ChannelInboundHandler的channelReadComplete(ChannelHandlertext)方法 |

| fireChannelWritabilityChanged | 调用ChannelPipeline中下一个ChannelInboundHandler的channelWritabilityChanged(ChannelHandlertext)方法 |

ChannelPipelin的出站操作

| 名称 | 描述 |

| — | — |

| bind | 将Channel绑定到一个本地地址,将调用ChannelPipeline中的下一个ChannelOutboundHandler的bind(ChannelHandlerContext,Socket,ChannelPromise)方法 |

| connect | 将Channel连接到一个远程地址,这将调用ChannelPipeline中的下一个ChannelOutboundHandler的connect(ChannelHandlerContext,Socket,ChannelPromise)方法 |

| disconnect | 将Channel断开连接。这将调用ChannelPipeline中的下一个ChannelOutboundHandler的disconnect(ChannelHandlerContext,Socket,ChannelPromise)方法 |

| close | 将Channel关闭。这将调用ChannelPipeline中的下一个ChannelOutboundHandler的close(ChannelHandlerContext,ChannelPromise)方法 |

| deregister | 将Channel从它先前分配的EventExecutor(即EventLoop)中注销,这将调用ChannelPipeline中的下一个ChannelOutboundHandler的deregister(ChannelHandlerContext,ChannelPromise)方法 |

| flush | 冲刷Channel所有挂起的写入。这将调用ChannelPipeline中的下一个ChannelOutboundHandler的flush(ChannelHandlerContext)方法 |

| write | 将消息写入Channel。这将调用ChannelPipeline中的下一个ChannelOutboundHandler的write(ChannelContext,Object msg,ChannelPromise)方法。这并不会将消息写入底层的Socket,而只会将它放入到队列中。要将它写入到Socket,需要调用flush或者writeAndFlush方法 |

| writeAndFlush | 先调用write再调用flush的便利方法 |

| read | 请求从Channel中读取更多的数据。这将调用ChannelPipeline中的下一个ChannelOutboundHandler的read(ChannelHandlerContext)方法 |

  1. ChannelPipeline保存了与Channel相关联的ChannelHandler

  2. ChannelPipeline可以根据需要,通过添加或者删除ChannelHandler来动态修改

  3. ChannelPipeline有着丰富的API调用,以响应入站和出站事件

ChanneHandlerContext接口

======================

ChannelHandlerContext代表了ChannelHandler和ChannelPipeline之间的关联。每当有ChannelHandler添加到ChannelPipeline中时,都会创建ChannelHandlerContext。ChannelHandlerContext的主要功能是管理它所关联的ChannelHandler和在同一个ChannelPipeline中的其他ChannelHandler之间的交互。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值