Подсчет записанных и прочитанных байтов в приложении netty

Мне нужно отслеживать индивидуальные клиентские соединения (записанные, считанные байты и скорость (байты в секунду)) в моем простом приложении http-сервера netty. Как я понимаю, для этого мне нужно использовать 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();
    }

}

1 ответ

@TMS, чтобы иметь возможность получать статистику, сначала нужно выбрать уровень статистики: для канала, глобально или для обоих.

  • ChannelTrafficShapingHandler: вы должны создать один элемент на канал (как вы это делали в своем конвейере), он связан с одним и только одним каналом. Статистика только по каналам, а не глобальная.

  • GlobalTrafficShapingHandler: вы должны создать его перед любым каналом и назначить его каждому каналу, как вы это делали, но каждый раз повторно использовать один и тот же объект (без перераспределения). Статистика только глобальная, а не по каналам.

  • GlobalChannelTrafficShapingHandler: вы должны создать его раньше (как для GlobalTSH) и назначить его каждому каналу (без перераспределения). Статистика является глобальной и на канал.

После того, как вы решили, какой из них для вас, есть в основном 2 способа получить статистику:

  1. Через конвейерный доступ: получение доступа к обработчику, а затем:
    • с помощью trafficCounter() метод доступа к объекту TrafficCounter:
      • для канала (только ChannelTSH)
      • для глобального видения (GlobalTSH или GlobalChannelTSH).
    • с помощью channelTrafficCounters() получить доступ ко всем TrafficCounters для всех активных каналов (только GlobalChannelTSH)
  2. Расширяя базовый класс (один из ChannelTSH, GlobalTSH или GlobalChannelTSH) и, в частности, protected void doAccounting(TrafficCounter counter) метод.

Вы можете посмотреть на один пример, созданный для Netty, но не импортированный окончательно в основной поток, который показывает, как его расширить и как его использовать: посмотрите здесь и, в частности, как расширить GlobalChannelTSH или как включить его в ваш конвейер здесь.

Конечно, вы могли бы взглянуть на API, который также частично объясняет это.

Наконец, если вы хотите иметь как статистику для канала, так и глобально, у вас есть выбор:

  • либо использовать GlobalChannelTSH (только один повторно используется все время), но вы должны сами проверить, какой канал подключен к какому TrafficCounter (используя name()) (GlobalChannelTSH в основном намеревается ограничить влияние памяти на распределение трафика при выполнении его на обоих уровнях, по каналам и в глобальном масштабе, но при использовании только для статистики, вероятно, не лучший выбор);
  • либо используйте ChannelTSH (так что прямой доступ к TrafficCounter для каждого канала) и GlobalTSH (только для глобального TrafficCounter).
Другие вопросы по тегам