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

2022-09-03 08:03:05

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

您可以在此处查看旧代码:https://github.com/outbrain/ob1k/blob/6364187b30cab5b79d64835131d9168c754f3c09/ob1k-core/src/main/java/com/outbrain/ob1k/common/metrics/NettyQueuesGaugeBuilder.java

  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++;
      }
    }
  }

我的问题是,有没有更好的方法来监视队列大小?

这可能是一个非常有用的指标,因为它可用于了解延迟,并且在某些情况下也可用于施加背压。


答案 1

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

为此,您可以创建一个包装和/或扩展 的类。然后,您将有一个,每次添加新任务以及每次删除/完成一个任务时,您都会调用它。SingleThreadEventExecutorjava.util.concurrent.atomic.AtomicIntegerincrementAndGet()decrementAndGet()

然后,AtomicInteger将为您提供当前挂起的任务数。你可能会覆盖使用该值来代替(尽管要小心 - 我不是100%不会有副作用)。pendingTasks()

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

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

铌。这只是一个关于如何解决这个问题的建议 - 我没有专门与Netty一起做这件事。虽然我过去用其他代码做过这种事情。


答案 2

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