2

次のサーバー ブートストラップ コードを検討してください。

ChannelFuture f;
ServerBootstrap b = new ServerBootstrap();

try {
    b.group(new NioEventLoopGroup(), new NioEventLoopGroup())
            .channel(NioServerSocketChannel.class)
            .localAddress(1234)
            .childOption(ChannelOption.TCP_NODELAY, true)
            .childHandler(new MyChannelInitializer(new DefaultEventExecutorGroup(10)));

    f = b.bind().sync();
    f.channel().closeFuture().sync();
}

そしてMyChannelInitializer.java :

public class MyChannelInitializer  extends ChannelInitializer<SocketChannel> {
    private EventExecutorGroup executorGroup;

    public MyChannelInitializer(EventExecutorGroup _executorGroup) {
        executorGroup = _executorGroup;
    }

    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

        pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.nulDelimiter()));
        pipeline.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
        pipeline.addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));

        // and then business logic.
        pipeline.addLast(this.executorGroup, "handler", new MyHandshakeHandler());
    }    
}

現在、MyHandshakeHandler() はメッセージをリッスンしており、これらのメッセージはデータベースと対話する必要があります。

さらに先に進む前に、上記のコードはこれを行う正しい方法ですか? (つまり、このブロッキングタイプのハンドラーに EventExecutorGroup を使用した方法)

今のところそれが正しいと仮定して、ここに私の質問があります。MyHandshakeHandler() がデータベースと対話する必要があるのは事実ですが、これはクライアントとの最初のネゴシエーション中およびチャネルのクローズ時のみです。残りの時間、つまりハンドシェイクが完了してチャネルが閉じられる前に必要なのは、データベースを必要としない ping/pong/heartbeat/keepalive タイプのメッセージをバウンスすることだけです。したがって、A) MyHandshakeHandler の前にパイプラインに追加される別のハンドラー (「MyPingHandler」と呼びましょう) にする必要がありますか、または B) そのロジックを MyHandshakeHandler に追加するだけですか?

A) 特にチャネルを閉じるイベント (つまり、channelInactive()) でない限り、MyHandshakeHandler が不必要に呼び出されないように、メッセージの伝播を停止するにはどうすればよいですか? おまけとして、MyPingHandler が不要に呼び出されないように、ハンドシェイクが完了した後にのみパイプラインに追加されると便利です。

B) この場合の EventExecutorGroup の目的がわかりません。これらの接続は、このサーバーが機能する唯一のタイプです....したがって、デフォルトを使用するのではなく、すべての単一ハンドラーに使用されるスレッドの専用グループを設定するのは奇妙に思えます。したがって、B が進むべき道である場合 (この特定のケースの場合)、EventExecutorGroup を使用せずに通常どおりハンドラーをパイプラインに追加する必要があります (そうでない場合)。

4

1 に答える 1

3

答えは(ア)です。

イベントを次のハンドラーに伝達するには、通常、ctx.fireXXX()メソッドを呼び出します。それらのいずれも呼び出さない場合、イベントは伝播されません。したがって、あなたの場合、メソッドを呼び出さないctx.fireXXX()ことでハンドシェイクが完了した後、ほとんどの場合、イベントを飲み込むことができます。

また、パイプラインは動的に構成できます。いつでもパイプラインにハンドラーを追加したり、パイプラインからハンドラーを削除したりできます。したがって、ハンドシェイクが終了した後にハンドシェイク ハンドラーを削除するか、ハンドシェイクが終了した後に ping ハンドラーを追加することができます (または両方)。

于 2012-11-05T07:48:24.387 に答える