netty

时间:2017-05-19 04:52:41

标签: java netty

查看文档,它说:

https://netty.io/4.0/api/io/netty/channel/ChannelPipeline.html

  

用户应该在管道中拥有一个或多个ChannelHandler   接收I / O事件(例如读取)并请求I / O操作(例如,   写和关闭)。例如,典型的服务器将具有   在每个渠道的管道中跟随处理程序,但您的里程可能   取决于协议的复杂性和特征   和业务逻辑:

     

协议解码器 - 将二进制数据(例如ByteBuf)转换为Java   宾语。   协议编码器 - 将Java对象转换为二进制数据。

     

业务逻辑处理程序 - 执行实际的业务逻辑(例如   数据库访问)。它可以表示如下所示   以下示例:static final EventExecutorGroup group = new   DefaultEventExecutorGroup(16); ...

     

ChannelPipeline pipeline = ch.pipeline();

     

pipeline.addLast(" decoder",new MyProtocolDecoder());

     

pipeline.addLast(" encoder",new MyProtocolEncoder());

     

//告诉管道运行MyBusinessLogicHandler的事件处理程序   方法//在与I / O线程不同的线程中进行I / O.   某个耗时的任务不会阻止线程。 // 如果你的   业务逻辑完全异步或很快完成,你   不要//指定一个组。

     

pipeline.addLast(group," handler",   新的MyBusinessLogicHandler());

在Github上的很多例子中,我看到了同样的模式。我想知道是否有人可以解释为什么businessHandler不在解码器和编码器之间。我认为你会获得你的POJO,然后在业务处理程序中对它进行处理,然后对其进行编码。

3 个答案:

答案 0 :(得分:2)

由于调用处理程序的顺序,解码器和编码器通常位于管道的开头。对于传入的数据,它是自下而上的,也是自上而下的传出。

E.g。

pipeline.addLast(new MyEncoder());
pipeline.addLast(new MyDecoder());
pipeline.addLast(new MyBusiness());

在这种情况下,对于传入数据,呼叫顺序是:MyDecoder(将数据转换为POJO) - > MyBusiness(不为传入流调用编码器)和传出数据:MyBusiness - > MyEncoder(没有为传出流调用解码器)。

如果您在业务处理程序中接收到传入流(实际上,解码器之后的POJO)对其进行处理并将其写回,则看起来MyBusiness位于编码器和解码器之间,因为数据正在返回编码器。

答案 1 :(得分:1)

当然,业务处理程序位于解码器和编码器之间。以Factorial示例为例。

   public void initChannel(SocketChannel ch) {
    ChannelPipeline pipeline = ch.pipeline();
    if (sslCtx != null) {
        pipeline.addLast(sslCtx.newHandler(ch.alloc()));
    }
    // Enable stream compression (you can remove these two if unnecessary)
    pipeline.addLast(ZlibCodecFactory.newZlibEncoder(ZlibWrapper.GZIP));
    pipeline.addLast(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP));
    // Add the number codec first,
    pipeline.addLast(new BigIntegerDecoder());
    pipeline.addLast(new NumberEncoder());
    // and then business logic.
    // Please note we create a handler for every new channel
    // because it has stateful properties.
    pipeline.addLast(new FactorialServerHandler());
}`

initChannel函数中认为管道首先添加编码器和解码器,最后添加处理程序。执行流程实际上由解码器,处理程序和编码器排序。 解码器,处理程序和编码器等处理程序实际存储在AbstractChannelHandlerContext类中。这是netty中AbstractChannelHandlerContext的链接列表。列表的排列方式如decoder context - > handler context - > encoder context,执行方式相同!

答案 2 :(得分:0)

实际上,如果在服务器中添加1.解码器,2。businessHandler,3。编码器,然后编写ctx.channel().writeAndFlush()ctx.pipeline().writeAndFlush(),则将调用编码器。在这种情况下是bc,它将从尾部开始查找上一个outboundChannel。但是,如果您编写ctx.writeAndFlush(),它将从businessHandler的位置查找prev outboundChannel。 在AbstractChannelHandlerContext的findContextOutbound()的第一行中添加一个断点,即可得到它。

private AbstractChannelHandlerContext findContextOutbound(int mask) {
        AbstractChannelHandlerContext ctx = this;
        EventExecutor currentExecutor = executor();
        do {
            ctx = ctx.prev;
        } while (skipContext(ctx, currentExecutor, mask, MASK_ONLY_OUTBOUND));
        return ctx;
    }