首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Netty责任链Pipeline详解

Netty责任链Pipeline详解

作者头像
IT架构圈
发布2020-12-16 10:42:09
2.6K0
发布2020-12-16 10:42:09
举报
文章被收录于专栏:IT架构圈IT架构圈

一起说说Netty责任链,责任链这块是netty运行机制的核心,一起来完整的了解下netty的责任链。

(一)责任链模式
  • ① 介绍

责任链模式(Chain of Responsibility Pattern) 为请求创建了一个处理对象的链。一个请求过来后,就交给一个责任链进行调用。在责任链里面定义很多很多的handler,具体请求这个程序的handler,请求者不关心,多少个步骤,多少次,只负责发送到责任链上,请求传递的细节不关心。

  • ② 实现责任链模式

处理器抽象类,具体的处理器实现类,保存处理器信息,处理执行。

  • ③ 源码分析
// -----链表形式调用------netty就是类似的这种形式
public class PipelineDemo {
    /**
     * 初始化的时候造一个head,作为责任链的开始,但是并没有具体的处理
     */
    public HandlerChainContext head = new HandlerChainContext(new AbstractHandler() {
        @Override
        void doHandler(HandlerChainContext handlerChainContext, Object arg0) {
            handlerChainContext.runNext(arg0);
        }
    });

    public void requestProcess(Object arg0) {
        this.head.handler(arg0);
    }

    public void addLast(AbstractHandler handler) {
        HandlerChainContext context = head;
        while (context.next != null) {
            context = context.next;
        }
        context.next = new HandlerChainContext(handler);
    }


    public static void main(String[] args) {
        PipelineDemo pipelineChainDemo = new PipelineDemo();
        pipelineChainDemo.addLast(new Handler2());
        pipelineChainDemo.addLast(new Handler1());
        pipelineChainDemo.addLast(new Handler1());
        pipelineChainDemo.addLast(new Handler2());

        // 发起请求
        pipelineChainDemo.requestProcess("火车呜呜呜~~");

    }
}

/**
 * handler上下文,我主要负责维护链,和链的执行
 */
class HandlerChainContext {
    HandlerChainContext next; // 下一个节点
    AbstractHandler handler;

    public HandlerChainContext(AbstractHandler handler) {
        this.handler = handler;
    }

    void handler(Object arg0) {
        this.handler.doHandler(this, arg0);
    }

    /**
     * 继续执行下一个
     */
    void runNext(Object arg0) {
        if (this.next != null) {
            this.next.handler(arg0);
        }
    }
}

// 处理器抽象类
abstract class AbstractHandler {
    /**
     * 处理器,这个处理器就做一件事情,在传入的字符串中增加一个尾巴..
     */
    abstract void doHandler(HandlerChainContext handlerChainContext, Object arg0); // handler方法
}

// 处理器具体实现类
class Handler1 extends AbstractHandler {
    @Override
    void doHandler(HandlerChainContext handlerChainContext, Object arg0) {
        arg0 = arg0.toString() + "..handler1的小尾巴.....";
        System.out.println("我是Handler1的实例,我在处理:" + arg0);
        // 继续执行下一个
        handlerChainContext.runNext(arg0);
    }
}

// 处理器具体实现类
class Handler2 extends AbstractHandler {
    @Override
    void doHandler(HandlerChainContext handlerChainContext, Object arg0) {
        arg0 = arg0.toString() + "..handler2的小尾巴.....";
        System.out.println("我是Handler2的实例,我在处理:" + arg0);
        // 继续执行下一个
        handlerChainContext.runNext(arg0);
    }
}

(二)Netty中的ChannelPipeline责任链
  • ① 介绍

pipeline管道保存了通道所有处理器信息,创建channel时自动创建一个专有的pipeline,入站事件和出站事件会调用pipeline上的处理器。

  • ② 入站事件和出站事件

入站事件:通常指IO线程生成了入站数据

(通俗理解:从socket底层自己往上冒上来的事件都是入站) 比如EventLoop收到selector的OP_READ事件,入站处理器调用socketChannel.read(ByteBuffer)接受到数据后,这将导致通道的ChannelPipeline中包含的下一个中的channelRead方法被调用

出站事件:通常指IO线程执行实际的输出操作

(通俗理解:想主动往socket底层操作的事件的都是出站) 比如bind方法用时请求server socket绑定到给定的SocketAddress,这将导致通道的ChannelPipeline中包含的下一个出站处理器中的bind方法被调用

  • ③ Nettty中定义的事件
  • ④ Pipeline中的handler是什么

ChannelHeadler

用于处理I/O事件或者拦截I/O操作,并转发到ChannelPipeline中下一个处理器。这个顶级接口定义功能很弱,实际使用时会去实现下面两大子接口:处理入站I/O事件的ChannelInboundHandler、处理出站I/O操作的ChannelOutboundHandler

适配器类

为了方便开发,避免所有handler去实现一遍接口方法,Netty提供了简单的实现类: ChannelInboundHandlerAdapter处理入站I/O事件 ChannelOutboundHandlerAdapter处理出站I/O事件 ChannelDuplexHandler支持同时处理入站和出站事件

ChannelHandlerContext

实际存储在Pipeline中的并非是ChannelHandler,而是上下文对象。将Handler包裹在上下文对象中,通过上下文对象与它所属的ChannelPipeline交互,向上或向下传递事件或者修改pipeline都是通过上下文对象。

  • ⑤ 那么如何维护Pipeline中的handler呢

ChannelPipeline是线程安全的,ChannelHandler可以在任何时候添加或者删除。例如你可以在即将交换敏感信息时插入加密处理程序,并在交换后删除它。一般操作,初始化的时候增加进去,较少删除。下面是Pipeline中管理的API

除了register方法还有bind方法,bind方法时出站事件执行顺序和入站事件相反

请求过来以后又是如何处理的呢?我们通过Accept事件获取请求,所以我们应该去看accept入站事件是如何处理的,

PS:用户在管道中有一个或者多个channelhandler来接收I/O事件(例如读取)和请求I/O操作(例如写入和关闭)一个典型的服务器在每个通道的管道中都有以下处理程序,但是根据协议和业务逻辑的复杂性和特征,可能会有所不同。 协议解码器--将二进制数据(例如ByteBuf)转换为Java对象 协议编码器--将java对象转化为二进制数据 业务逻辑处理程序--执行实际的业务逻辑(例如访问数据库)

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-12-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程坑太多 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • (一)责任链模式
  • (二)Netty中的ChannelPipeline责任链
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档