Подсчет записанных и прочитанных байтов в приложении 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 способа получить статистику:
- Через конвейерный доступ: получение доступа к обработчику, а затем:
- с помощью
trafficCounter()
метод доступа к объекту TrafficCounter:- для канала (только ChannelTSH)
- для глобального видения (GlobalTSH или GlobalChannelTSH).
- с помощью
channelTrafficCounters()
получить доступ ко всем TrafficCounters для всех активных каналов (только GlobalChannelTSH)
- с помощью
- Расширяя базовый класс (один из ChannelTSH, GlobalTSH или GlobalChannelTSH) и, в частности,
protected void doAccounting(TrafficCounter counter)
метод.
Вы можете посмотреть на один пример, созданный для Netty, но не импортированный окончательно в основной поток, который показывает, как его расширить и как его использовать: посмотрите здесь и, в частности, как расширить GlobalChannelTSH или как включить его в ваш конвейер здесь.
Конечно, вы могли бы взглянуть на API, который также частично объясняет это.
Наконец, если вы хотите иметь как статистику для канала, так и глобально, у вас есть выбор:
- либо использовать GlobalChannelTSH (только один повторно используется все время), но вы должны сами проверить, какой канал подключен к какому TrafficCounter (используя
name()
) (GlobalChannelTSH в основном намеревается ограничить влияние памяти на распределение трафика при выполнении его на обоих уровнях, по каналам и в глобальном масштабе, но при использовании только для статистики, вероятно, не лучший выбор); - либо используйте ChannelTSH (так что прямой доступ к TrafficCounter для каждого канала) и GlobalTSH (только для глобального TrafficCounter).