2015-10-04 19 views
13

Wir haben die Überwachung für die Netty-Ereignisschleifenwarteschlangen implementiert, um Probleme mit einigen unserer Netty-Module zu verstehen. Der Monitor verwendet die io.netty.util.concurrent.SingleThreadEventExecutor#pendingTasks-Methode, die für die meisten Module funktioniert, aber für ein Modul, das einige tausend HTTP-Anfragen pro Sekunde verarbeitet, scheint es hängen zu bleiben oder sehr langsam. Ich erkenne jetzt, dass die Dokumente streng angeben, dass dies ein Problem sein kann, und ich fühle mich ziemlich lahm ... so suche ich nach einer anderen Möglichkeit, diesen Monitor zu implementieren.Überwachen der Größe der Netty-Ereignisschleifenwarteschlangen

Sie können den alten Code sehen hier: 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++; 
     } 
    } 
    } 

Meine Frage ist, gibt es einen besseren Weg, um die Warteschlange Größen zu überwachen?

Dies kann eine ziemlich nützliche Metrik sein, da sie verwendet werden kann, um die Latenz zu verstehen, und in einigen Fällen auch für das Anlegen von Gegendruck verwendet werden kann.

Antwort

1

Sie müssten die Änderungen wahrscheinlich als Aufgaben verfolgen, die aus den Instanzen SingleThreadEventExecutor hinzugefügt oder entfernt wurden.

Um dies zu tun, könnten Sie eine Klasse erstellen, die SingleThreadEventExecutor umschließt und/oder erweitert. Dann hätten Sie eine java.util.concurrent.atomic.AtomicInteger, die Sie jedes Mal, wenn eine neue Aufgabe hinzugefügt wird, incrementAndGet() aufrufen und decrementAndGet() jedes Mal, wenn eine entfernt/beendet wird.

Dieser AtomicInteger würde Ihnen dann die aktuelle Anzahl der ausstehenden Aufgaben geben. Sie könnten wahrscheinlich pendingTasks() überschreiben, um stattdessen diesen Wert zu verwenden (seien Sie aber vorsichtig - ich bin nicht 100%, das hätte keine Nebenwirkungen).

Es würde zu jeder ausgeführten Aufgabe einen kleinen Overhead hinzufügen, würde aber die Anzahl der ausstehenden Aufgaben fast konstant halten.

Der Nachteil ist natürlich, dass es invasiver ist als das, was Sie gerade tun, da Sie Ihre App für die Verwendung verschiedener Event-Executoren konfigurieren müssen.

NB. Dies ist nur ein Vorschlag, wie Sie das Problem umgehen können - ich habe dies nicht explizit mit Netty getan. Obwohl ich in der Vergangenheit so etwas mit anderem Code gemacht habe.

+0

Ich mag nicht die Idee, sich zu sehr auf interne Details zu verlassen. Was ich zu tun habe, ist, eine Aufgabe periodisch zu planen, um die Größe der Warteschlange innerhalb des Ereignisschleife-Threads zu überprüfen. Nicht so genau, aber gut für die Überwachung. –