Netty原理:ChannelHandler

x33g5p2x  于2021-11-25 转载在 其他  
字(1.9k)|赞(0)|评价(0)|浏览(405)
ChannelHandler

类层次关系图

入站和出站:
从服务端的角度,数据从客户端发送到服务端,称之为入站,当数据处理完成返回给客户端,称之为出站。是相对的概念。

从客户端的角度,数据从服务端发送给客户端,称之为入站,当数据返回给服务端,称之为出站。

不论是入站还是出站,handler从一端开始,到另一端结束,以责任链的模式依次执行。

责任链模式——“击鼓传花”,当请求被不同的接收者处理时,每个接收者都包含对下一个接收者的引用,一个接收者处理完成后,将依次向下传递。

适配器模式——出国时要使用的电源转换器(美国/日本110V 中国220V电压),作为两个不兼容的接口之间的桥梁,将类的接口转换为需要的另外一种接口。

ChannelDuplexHandler是除了入站和出站handler之外的,另一个常用子类。
它同时实现了ChannelInboundHandler和ChannelOutboundHandler接口,如果需要既处理入站事件又处理出站事件,可以继承此类。

  1. serverBootstrap.handler(new LoggingHandler(LogLevel.INFO))
  2. ------------------------------------------------------------------
  3. public class LoggingHandler extends ChannelDuplexHandler{}
  4. ------------------------------------------------------------------
  5. public class ChannelDuplexHandler extends ChannelInboundHandlerAdapter implements ChannelOutboundHandler {}
  6. ------------------------------------------------------------------
  7. public class ChannelInboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelInboundHandler {}

ChannelHandlerAdapter
提供了额外的isSharable()方法,用来判断handler是否可以被共享到多个pipeline之中。默认情况不共享,如果需要共享,在继承了适配器的handler上,增加注解@Sharable

  1. @Sharable
  2. public class LoggingHandler extends ChannelDuplexHandler {}

ChannelInboundHandler
最重要的方法是channelRead(),在使用时,需要显式 释放ByteBuf相关的内存。使用ReferenceCountUtil是引用计数的工具类。

  1. @Override
  2. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  3. // netty中的缓冲区 叫做ByteBuf -- 对ByteBuffer的封装
  4. ByteBuf buf = (ByteBuf) msg;
  5. // 释放ByteBuf内存
  6. ReferenceCountUtil.release(msg);
  7. }

为了减少对资源内存的管理,使用SimpleChannelInboundHandler,使用其channelRead0()方法,可以自动释放资源,使用更便利。

  1. SimpleChannelInboundHandler源码
  2. ------------------------------------------------
  3. @Override
  4. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  5. boolean release = true;
  6. try {
  7. if (acceptInboundMessage(msg)) {
  8. @SuppressWarnings("unchecked")
  9. I imsg = (I) msg;
  10. channelRead0(ctx, imsg);
  11. } else {
  12. release = false;
  13. ctx.fireChannelRead(msg);
  14. }
  15. } finally {
  16. if (autoRelease && release) {
  17. ReferenceCountUtil.release(msg);
  18. }
  19. }
  20. }

相关文章