Java 监视Netty事件循环队列的大小

Java 监视Netty事件循环队列的大小,java,netty,monitoring,event-loop,Java,Netty,Monitoring,Event Loop,我们已经实现了对Netty事件循环队列的监视,以便了解一些Netty模块的问题。 监视器使用io.netty.util.concurrent.SingleThreadEventExecutor#pendingTasks方法,该方法适用于大多数模块,但对于每秒处理数千个HTTP请求的模块,它似乎挂起,或者非常慢。 我现在意识到,文件严格规定这可能是一个问题,我感到相当跛脚。。。所以我正在寻找另一种方法来实现这个监视器 您可以在此处看到旧代码: 公共静态无效注册表QueueGauges(最终Met

我们已经实现了对Netty事件循环队列的监视,以便了解一些Netty模块的问题。 监视器使用
io.netty.util.concurrent.SingleThreadEventExecutor#pendingTasks
方法,该方法适用于大多数模块,但对于每秒处理数千个HTTP请求的模块,它似乎挂起,或者非常慢。 我现在意识到,文件严格规定这可能是一个问题,我感到相当跛脚。。。所以我正在寻找另一种方法来实现这个监视器

您可以在此处看到旧代码:

公共静态无效注册表QueueGauges(最终MetricFactory工厂、最终EventLoopGroup elg、最终字符串组件名称){
int指数=0;
对于(最终事件执行者事件执行者:elg){
if(单线程事件执行器的事件执行器实例){
最终SingleThreadEventExecutor singleExecutor=(SingleThreadEventExecutor)eventExecutor;
registerGauge(“EventLoopGroup-”+组件名称,“EventLoop-”+索引,新仪表(){
@凌驾
公共整数getValue(){
返回singleExecutor.pendingTasks();
}
});
索引++;
}
}
}
我的问题是,有没有更好的方法来监控队列大小


这可能是一个非常有用的指标,因为它可以用来理解延迟,在某些情况下也可以用来施加反压力。

您可能需要将这些更改作为任务跟踪,作为从
SingleThreadEventExecutor
实例中添加和删除的任务

为此,您可以创建一个类来包装和/或扩展
SingleThreadEventExecutor
。然后,您将拥有一个
java.util.concurrent.AtomicInteger
,每次添加新任务时,您都会调用它
incrementAndGet()
,每次删除/完成任务时,都会调用它

该AtomicInteger将为您提供当前挂起任务的数量。您可能会重写
pendingTasks()
以使用该值(尽管在这里要小心-我不是100%不会有副作用)

它会给正在执行的每个任务增加一点开销,但会使检索挂起任务的数量接近恒定速度

当然,这样做的缺点是,它比您目前所做的更具侵入性,因为您需要将应用程序配置为使用不同的事件执行器


注意。这只是一个关于如何解决这个问题的建议——我并没有专门针对Netty这样做。尽管我过去也用其他代码做过类似的事情。

现在,在2021年,Netty在内部使用JCTools队列,并且
pendingTasks()
执行速度非常快(几乎总是恒定时间),因此即使javadoc仍然声明此操作速度缓慢,您也可以毫无顾虑地使用它。
以前的问题是,计算队列中的元素是一个线性操作,但在迁移到JCTools库后,这个问题消失了。

我不喜欢过分依赖内部细节的想法。我想我要做的是定期安排一个任务,从事件循环线程中检查队列大小。没有那么准确,但对监控来说很好。
  public static void registerQueueGauges(final MetricFactory factory, final EventLoopGroup elg, final String componentName) {

    int index = 0;
    for (final EventExecutor eventExecutor : elg) {
      if (eventExecutor instanceof SingleThreadEventExecutor) {
        final SingleThreadEventExecutor singleExecutor = (SingleThreadEventExecutor) eventExecutor;
        factory.registerGauge("EventLoopGroup-" + componentName, "EventLoop-" + index, new Gauge<Integer>() {
          @Override
          public Integer getValue() {
            return singleExecutor.pendingTasks();
          }
        });

        index++;
      }
    }
  }