计算netty应用程序中的写入和读取字节数

时间:2015-08-02 12:14:50

标签: netty trafficshaping

我需要在我的简单http服务器netty app中跟踪各个客户端的连接(写入,读取字节和速度(每秒字节数))。据我了解,要做到这一点,我必须使用ChannelTrafficShapingHandler。 必须覆盖哪些方法以及如何进行这些计算?

My 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());
    }
}

My 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 个答案:

答案 0 :(得分:3)

@TMS,为了能够获得统计数据,首先需要选择统计级别:每个频道,全局或两者。

  • ChannelTrafficShapingHandler:您必须为每个频道创建一个项目(就像您在管道中所做的那样),它只链接到一个频道。统计数据仅针对每个渠道,而非全球统计。

  • GlobalTrafficShapingHandler:您必须在任何频道之前创建它并将其分配给每个频道,但每次都重复使用相同的对象(不重新分配)。统计数据仅为全局,而非每个渠道。

  • GlobalChannelTrafficShapingHandler:您必须先创建它(与GlobalTSH一样)并将其分配给每个通道(不重新分配)。统计数据是全球性的,每个渠道。

一旦你决定哪一个适合你,主要有两种方法来获取统计数据:

  1. 通过管道访问:访问处理程序,然后:
    • 使用trafficCounter()方法访问TrafficCounter对象:
      • 用于频道(仅限ChannelTSH)
      • 为全球视野(GlobalTSH或GlobalChannelTSH)。
    • 使用channelTrafficCounters()访问所有有效渠道的所有TrafficCounters(仅限GlobalChannelTSH)
  2. 通过扩展基类(ChannelTSH,GlobalTSH或GlobalChannelTSH之一),特别是protected void doAccounting(TrafficCounter counter)方法。
  3. 您可以查看为Netty制作但最终未在主流中导入的示例,该示例显示了如何扩展和使用它:see here,特别是how to extend GlobalChannelTSHhow to include it in your pipeline here

    当然,你可以看一下the API部分解释这一点。

    最后,如果您想同时拥有频道和全局统计信息,您可以选择:

    • 要么使用GlobalChannelTSH(只有一个重复使用),但你必须检查自己哪个通道连接到哪个TrafficCounter(使用name())(GlobalChannelTSH主要是为了限制内存对流量抖动的影响)在两个级别,每个通道和全局上执行此操作,但仅在用于统计信息时,可能不是最佳选择);
    • 使用ChannelTSH(因此可以直接访问每个频道的TrafficCounter)和GlobalTSH(仅限全局TrafficCounter)。