0

シンプルな http サーバーの netty アプリで、個々のクライアントの接続 (書き込み、読み取りバイト数、および速度 (1 秒あたりのバイト数)) を追跡する必要があります。私が理解しているように、これを行うには、を使用する必要がありますChannelTrafficShapingHandler。どのメソッドをオーバーライドする必要があり、これらの計算をどのように行うことができますか?

私のChannelInitializer:

public class HttpServerInitializer extends ChannelInitializer<SocketChannel> {

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

        pipeline.addLast("codec", new HttpServerCodec())
                .addLast("traffic", new TrafficShapingHandler(AbstractTrafficShapingHandler.DEFAULT_CHECK_INTERVAL))
                .addLast("handler", new HttpServerHandler());
    }
}

私の SimpleChannelInboundHandler:

public class HttpServerHandler extends SimpleChannelInboundHandler<HttpRequest> {

    private static DefaultChannelGroup activeChannels = new DefaultChannelGroup("netty-receiver", ImmediateEventExecutor.INSTANCE);

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        activeChannels.add(ctx.channel());
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpRequest req) throws Exception {
        if (is100ContinueExpected(req)) {
            ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE));
        }

        String uri = req.getUri().toLowerCase();

        Controller controller = ControllerFactory.getController(uri);

        FullHttpResponse response = controller.getResponse();

        if (controller instanceof HelloController) {
            ctx.executor().schedule(() -> ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE), 3, TimeUnit.SECONDS);
        } else {
            ctx.write(response).addListener(ChannelFutureListener.CLOSE);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

    public static long getConnectionsQuantity() {
        return activeChannels.size();
    }

}
4

1 に答える 1

3

@TMS、統計を取得できるようにするには、最初に統計のレベルを選択する必要があります: チャネルごと、グローバル、またはその両方。

  • ChannelTrafficShapingHandler: チャネルごとに 1 つのアイテムを作成する必要があります (パイプラインで行ったように)。これは 1 つのチャネルにのみリンクされます。統計は、グローバルではなくチャネルごとのみです。

  • GlobalTrafficShapingHandler: チャネルの前に作成し、各チャネルに割り当てる必要がありますが、毎回同じオブジェクトを再利用します (再割り当てなし)。統計はグローバルのみであり、チャネルごとではありません。

  • GlobalChannelTrafficShapingHandler: 事前に (GlobalTSH の場合と同様に) 作成し、各チャネルに割り当てる必要があります (再割り当てなし)。統計はグローバルでチャネルごとです。

どちらが適しているかを判断したら、主に 2 つの方法で統計情報を取得できます。

  1. パイプライン アクセスを介して: ハンドラーへのアクセスを取得してから:
    • メソッドを使用trafficCounter()して TrafficCounter オブジェクトにアクセスします。
      • チャネル用 (ChannelTSH のみ)
      • グローバル ビジョン (GlobalTSH または GlobalChannelTSH) の場合。
    • channelTrafficCounters()すべてのアクティブなチャネルのすべての TrafficCounters へのアクセスに使用(GlobalChannelTSH のみ)
  2. 基本クラス (ChannelTSH、GlobalTSH、または GlobalChannelTSH のいずれか) および具体的にはprotected void doAccounting(TrafficCounter counter)メソッドを拡張することによって。

Netty 用に作成されたものの、最終的にメイン ストリームにインポートされず、それを拡張して使用する方法を示す 1 つの例を見ることができます

もちろん、これも部分的に説明している APIを見ることができます。

最後に、チャネルとグローバルの両方の統計が必要な場合は、次の選択肢があります。

  • どちらかが GlobalChannelTSH を使用します (常に 1 つだけが再利用されます) が、どのチャネルがどの TrafficCounter に接続されているかを自分で確認する必要があります (を使用name()) (GlobalChannelTSH は主に、チャネルごとに両方のレベルでそれを行うときに、トラフィック シェーピングに対するメモリの影響を制限することを目的としています)およびグローバルに、ただし統計にのみ使用する場合は、おそらく最良の選択ではありません);
  • ChannelTSH (チャネルごとの TrafficCounter への直接アクセス) と GlobalTSH (グローバル TrafficCounter のみ) の両方を使用します。
于 2015-08-02T18:36:32.537 に答える