簡體   English   中英

netty 中的解碼器、編碼器、ServerHandler 管道

[英]Decoder, Encoder, ServerHandler pipeline in 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 管道 = ch.pipeline();

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

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

// 告訴管道在與 I/O 線程不同的線程中 // 運行 MyBusinessLogicHandler 的事件處理程序方法,以便 I/O 線程不會被耗時的任務阻塞 //。 // 如果您的業務邏輯是完全異步的或很快完成,您就不需要 // 指定一個組。

pipeline.addLast(group, "handler", new MyBusinessLogicHandler());

在 Github 上的許多示例中,我看到了相同的模式。 我想知道是否有人可以解釋為什么 businessHandler 不在解碼器和編碼器之間。 我認為你會得到你的 POJO,然后在業務處理程序中處理它,然后對它進行編碼。

由於調用處理程序的順序,解碼器和編碼器通常位於管道的開頭。 對於傳入的數據,它是自下而上的,而傳出的數據是自上而下的。

例如

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

在這種情況下,傳入數據的調用順序是:MyDecoder(將數據轉換為POJO)-> MyBusiness(傳入流不調用編碼器),傳出數據:MyBusiness -> MyEncoder(傳出流不調用解碼器) .

如果您在業務處理程序(實際上是解碼器之后的 POJO)中接收到傳入流並將其寫回,則看起來 MyBusiness 位於編碼器和解碼器之間,因為數據正在返回編碼器。

當然,業務處理程序介於解碼器和編碼器之間。以 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的函數中initChannel pipeline先添加encoder和decoder,最后添加handler。 執行流程實際上是按解碼器、處理程序和編碼器排序的。 解碼器、處理程序和編碼器等處理程序實際上存儲在AbstractChannelHandlerContext類中。 Netty 中有一個AbstractChannelHandlerContext的鏈表。 列表的排列方式是decoder context --> handler context --> encoder context ,執行是一樣的!

事實上,如果你在你的服務器中添加ctx.channel().writeAndFlush() ,並且你編寫ctx.channel().writeAndFlush()ctx.pipeline().writeAndFlush() ,那么編碼器將被調用. 在這種情況下是 bc,它將從尾部開始尋找上一個 outboundChannel。 但是,如果您編寫ctx.writeAndFlush() ,它將從 businessHandler 的位置查找上一個 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;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM