ネッティーパイプラインおよびそれらのものChannelHandler

パイプラインとChannelHandlerネッティーがChannelHandlerにトラフィックプロセッサ対応、プロセスフローの重要な部分であり、それぞれの「コンテナ」、処理の流れが一緒に網状にそれらを組み合わせて完成されて一緒に担当するパイプラインChannelHandler文字列です。

パイプライン

各チャネルは、パイプライン内部DefaultChannelPipelineのデフォルトの実装は、リストDefaultChannelHandlerContextを維持し、ChannelPipeline内部オブジェクトのパイプラインを保持します。

チャネルは、レジスタを完了したときに読んだときに、アクティブ、readComplete他の動作は、パイプラインは、対応するメソッドをトリガするチャンネルの読み取りと書き込み操作はDefaultChannelPipelineを、来ます。

  1. チャネルがセレクタに登録された場合、トリガーは、パイプラインの方法をfireChannelRegistered。
  2. チャネルが利用可能である場合、パイプラインのfireChannelActive方法をトリガします。(FireChannelActiveトリガーは、通常fireChannelRegistered後にトリガされます)。
  3. クライアントは、データ、パイプラインのトリガーfireChannelRead方法を送信すると、
  4. これは、パイプラインのfireChannelRead方法をトリガした後fireChannelReadComplete方法パイプラインをトリガします。

DefaultChannelPipelineネッティー・デフォルト・パイプラインが達成され、以下のように、対応するコードは次のようになります。

public class DefaultChannelPipeline implements ChannelPipeline {
    // head和tail是handler的处理链/上下文
    final AbstractChannelHandlerContext head;
    final AbstractChannelHandlerContext tail;
    private final Channel channel;
     
    protected DefaultChannelPipeline(Channel channel) {
        this.channel = ObjectUtil.checkNotNull(channel, "channel");
        succeededFuture = new SucceededChannelFuture(channel, null);
        voidPromise =  new VoidChannelPromise(channel, true);
  
        tail = new TailContext(this);
        head = new HeadContext(this);
        head.next = tail;
        tail.prev = head;
    }
}

TailContext ChannelOutboundHandlerインターフェイス、HeadContext ChannelOutboundHandlerインタフェース及び実装ChannelInboundHandler、頭部、尾状リンクリストを実装します。

インバウンド操作の場合、処理は、ヘッド後方トラバーサルから開始され、アウトバウンド操作のために、尾からの処理が開始されると、前方の横断を。だから、それが動作しないアウトバウンドであるインバウンドオペレーションは何ですか?

  • INBOUND:channelRegistered、channelActive、channelRead、channelReadComplete。
  • アウトバウンド:バインド、接続、近くに、フラッシュ等。

注、HeadContextを達成ChannelInboundHandlerし、ChannelOutboundHandlerOutbound操作のためのインタフェース、最後は、実際には、に対処するだけの浅いTailContextパッケージをHeadContext来る、実際のロジックはあまりないです。HeadContextはのための営業カテゴリー基盤となるソケットネッティー含まれているbind/connect/disconnect/close/deregister/beginRead/read/wirte/flush操作オブジェクトは、安全でないことによって実現されています。

final class HeadContext extends AbstractChannelHandlerContext
        implements ChannelOutboundHandler, ChannelInboundHandler {
 
    // netty的底层socket操作类
    private final Unsafe unsafe;
 
    HeadContext(DefaultChannelPipeline pipeline) {
        super(pipeline, null, HEAD_NAME, false, true);
        unsafe = pipeline.channel().unsafe();
        setAddComplete();
    }
    // ...
}

リストはchannelPipeline channelHandlerContext「責任の連鎖」モードは、要求の処理が複数ChannelHandler、このようdecodeHandler、カスタムビジネスChannelHandlerとencodeHandlerを伴うことが具体化されています。ビジネスchannelHandler例:

public class EchoHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf in = (ByteBuf) msg;
        System.out.println(in.toString(CharsetUtil.UTF_8));
        ctx.write(msg);
    }
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}

コールchannelReadComplete方法フラッシュが、実際には、head.flush方法、データを送信しますunsafe.flush最終呼び出しが来ます。網状パイプラインが責任鎖である(又はパイプライン)パイプライン機構によってモードを反映して、網状データ処理機構は、強力なスケーラビリティと柔軟性を有しています。

ChannelHandler

エンコーダ、デコーダ、および他のビジネスプロセス:チャネルは、複数のchannelHandler、channelHandlerいくつかのタイプを含むことができる、サービス処理ネッティー、どのように複雑な、ChannelHandlerを行うために作られてどんなにをもとに、ChannelHandlerネッティープロセッサです。

decoderHandler

次のようにほとんど又は受信データ処理decoderHandlerを変換した後、基本的にサブクラスByteToMessageDecoderクラス図です。

一時的なデータ格納バッファが存在しますByteToMessageDecoder、受信したデータが不完全な場合、あなたは次のステージング処理までデータが受信される次の時間を待つことができます。

encoderHandler

encoderHandlerは主に、メッセージデータ、次のようにクラス図であり、基本的にサブクラスMessageToByteEncoder bytebufに変換します。

ビジネスchannelHandler

ビジネスは、ユーザー定義、通常channel.pipelineにaddLastへの最後では、そのようなHTTP処理ロジックとしてchannelHanlerを処理し、ビジネス・ロジックで次のようになります。

ServerBootstrap boot = new ServerBootstrap();
boot.group(bossGroup, workerGroup)
    .channel(NioServerSocketChannel.class)
    .localAddress(8080)
    .childHandler(new ChannelInitializer<SocketChannel>() {
        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
            ch.pipeline()
                    .addLast("decoder", new HttpRequestDecoder())
                    .addLast("encoder", new HttpResponseEncoder())
                    .addLast("aggregator", new HttpObjectAggregator(512 * 1024))
                    .addLast("handler", new HttpHandler());
        }
    });

要求処理チェーンを形成し、ChannelHandlerContextを連結することにより、DefaultChannelPipeline headContext(ChannelOutboundHandlerが達成さChannelInboundHandler)、tailContext(ChannelOutboundHandlerを実現)と自己定義ChannelHandler(等decoderHandler、ecoderHandler、channelHandlerは、典型的にChannelInboundHandlerを実施します)。

ChannelOutboundHandler順序の間に2つの間の順序を保証することなく、秩序を確保するためにChannelInboundHandlerの間で、確実にするために:順序ChannelOutboundHandlerとChannelInboundHandler 1つだけを覚えて、実際には、追加どのように注意してください。

channelHandler的运行流程图:

TailContesxt本身代码不多并且挺多方法都是"空实现",不过它的channelRead方法内部会执行ReferenceCountUtil.release(msg)释放msg占用的内存空间,也就是说在未定义用户ChannelHandler或者用户ChannelHandler的channelRead继续传递后续ChannelHandler的channelRead时,到TailContext的channelRead时会自动释放msg所占用内存。

推荐阅读

欢迎小伙伴关注【TopCoder】阅读更多精彩好文。

おすすめ

転載: www.cnblogs.com/luoxn28/p/11963736.html