So rufen Sie die Thread-Dump-Analyse-API auf

In dieser modernen Welt werden Thread-Dumps immer noch in einem mühsamen und manuellen Modus analysiert, dh Sie müssen sich an das DevOps-Team wenden, es bitten, Ihnen die Thread-Dumps zu senden, dann werden sie Ihnen die Thread-Dumps mailen, dann werden Sie sie hochladen Dumps in ein Thread-Dump-Analysetool, dann müssen Sie Ihre Intelligenz anwenden, um es zu analysieren. Es gibt keine programmgesteuerte Möglichkeit, Thread-Dumps proaktiv zu analysieren. Um diesen Ärger zu beseitigen, führt fastthread.io eine RESTful-API ein, um Thread-Dumps zu analysieren. Mit einer Zeile des CURL-Befehls können Sie Ihre Thread-Dumps sofort analysieren lassen.

Hier sind einige Anwendungsfälle, in denen diese API äußerst nützlich sein kann.

Anwendungsfall 1: Automatische Ursachenanalyse

Die meisten DevOps rufen einen einfachen HTTP-Ping oder APM-Tools auf, um den Zustand der Anwendung zu überwachen. Dieser Ping ist gut, um festzustellen, ob die Anwendung aktiv ist oder nicht. APM-Tools sind hervorragend darin, darüber zu informieren, dass die CPU der Anwendung um ‘x%’ gestiegen ist, die Speicherauslastung um ‘y%’ gestiegen ist und die Antwortzeit um ‘z’ Millisekunden gesunken ist. Es wird nicht darüber informiert, was die CPU in die Höhe getrieben hat, was die Speicherauslastung erhöht hat, was die Reaktionszeit verschlechtert hat. Wenn Sie den Cron-Job so konfigurieren können, dass Thread-Dumps/GC-Protokolle in regelmäßigen Abständen erfasst und unsere REST-API aufgerufen werden, wenden wir unsere intelligenten Muster und Algorithmen für maschinelles Lernen an, um die Grundursache des Problems sofort zu identifizieren.

Vorteil 1: Wann immer diese Art von Produktionsproblem auftritt, recycelt das DevOps-Team aufgrund der Hitze des Gefechts die Server, ohne die Thread-Dumps und GC-Protokolle zu erfassen. Sie müssen Thread-Dumps und GC-Protokolle in dem Moment erfassen, in dem das Problem auftritt, um das Problem zu diagnostizieren. Bei dieser neuen Strategie müssen Sie sich darüber keine Gedanken machen, da Ihr Cron-Job Thread-Dumps/GC-Protokolle in regelmäßigen Abständen erfasst und die REST-API aufruft, alle Ihre Thread-Dumps/GC-Protokolle werden auf unseren Servern archiviert.

Vorteil 2: Im Gegensatz zu APM-Tools, die behaupten, weniger als 3 % des Overheads hinzuzufügen, wo sie in Wirklichkeit mehrere Falten hinzufügen, ist das Schöne an dieser Strategie: Sie fügt keinen Overhead (oder einen vernachlässigbaren Overhead) hinzu. Weil die gesamte Analyse der Thread-Dumps/GCeasy auf unseren Servern und nicht auf Ihren Produktionsservern durchgeführt wird.

Anwendungsfall 2: Leistungstests

Wenn Sie Leistungstests durchführen, möchten Sie möglicherweise regelmäßig Thread-Dumps/GC-Protokolle erstellen und diese über die API analysieren lassen. Falls die Anzahl der Threads einen Schwellenwert überschreitet oder wenn zu viele Threads WARTEN oder wenn Threads über einen längeren Zeitraum BLOCKIERT sind oder die Sperre nicht freigegeben wird oder häufig vollständige GC-Aktivitäten stattfinden oder die GC-Pausenzeit die Schwellenwerte überschreitet, muss sie erhalten werden die Sichtbarkeit genau dann und dort. Es sollte analysiert werden, bevor der Code in die Produktion gelangt. Unter solchen Umständen wird diese API sehr praktisch.

Anwendungsfall 3: Kontinuierliche Integration

Als Teil der kontinuierlichen Integration wird dringend empfohlen, Leistungstests durchzuführen. Thread-Dumps/GC-Protokolle sollten erfasst werden und können mithilfe der API analysiert werden. Wenn die API Probleme meldet, kann der Build fehlschlagen. Auf diese Weise können Sie den Leistungsabfall direkt während der Codeübergabezeit abfangen, anstatt ihn in Leistungslabors oder der Produktion abzufangen.

Wie rufe ich die Thread-Dump-Analyse-API auf?

Das Aufrufen der Thread-Dump-Analyse-API ist sehr einfach:

1.) Registrieren mit uns. Wir senden Ihnen den API-Schlüssel per E-Mail zu. Dies ist ein einmaliger Einrichtungsvorgang. Hinweis: Wenn Sie gekauft haben Unternehmensversion mit API, Sie müssen sich nicht registrieren. Der API-Schlüssel wird Ihnen als Teil der Installationsanleitung zur Verfügung gestellt.
2.) HTTP-Anfrage senden an
3.) Der Body des HTTP-Requests sollte den zu analysierenden Thread-Dump enthalten. Sie können entweder 1 Thread-Dump oder mehrere Thread-Dumps in derselben Anfrage senden.
4.) Die HTTP-Antwort wird im JSON-Format zurückgesendet. JSON hat mehrere wichtige Statistiken über den Thread-Dump. Das primäre Element, das in der JSON-Antwort zu suchen ist, ist: „Problem“. Die API wendet mehrere intelligente Thread-Dump-Analysemuster an und wenn sie Probleme erkennt, wird dies in diesem „Problem“-Element gemeldet.

CURL-Befehl
Angenommen, Ihre Thread-Dump-Datei befindet sich in „./my-thread-dump.txt“, dann lautet der CURL-Befehl zum Aufrufen der API:

curl -X POST --data-binary @./my-thread-dump.txt  --header "Content-Type:text"

Einfacher geht es nicht? Ist es nicht?

Kompression
Thread Dump sind ziemlich groß. Für eine schnelle und effiziente Verarbeitung empfehlen wir Ihnen, die Thread-Dump-Dateien zu komprimieren und zu senden. Wenn Sie den Thread-Dump komprimieren, müssen Sie das Element „Content-Encoding“ im HTTP-Header-Element oder im URL-Parameter übergeben.

Angenommen, Sie komprimieren die Thread-Dump-Datei in das ZIP-Format, dann können Sie die API mit dem HTTP-Header-Element aufrufen

curl -X POST --data-binary @./my-thread-dump.zip "" --header "Content-Type:text" --header "Content-Encoding:zip"

oder Sie können die API auch mit dem Element „Content-Encoding“ im URL-Parameter aufrufen

curl -X POST --data-binary @./my-thread-dump.zip "&Content-Encoding=zip" --header "Content-Type:text"

Wir unterstützen folgende Komprimierungsformate:

zip, gz, xz, z, lzma, entleeren, sz, lz4, zstd, bz2, tar

Sie können die Ihrer Wahl verwenden. Unabhängig davon, welches Komprimierungsformat Sie zum Komprimieren des Heap-Dumps verwendet haben, sollte es im Element „Content-Encoding“ übergeben werden.

Andere Werkzeuge
Sie können die API auch mit beliebigen Webservice-Client-Tools aufrufen, wie z. B.: SOAP UI, Postman Browser Plugin, …..

Postbote-ft.png
Abb: POSTing Thread-Dumps über das PostMan-Plugin

Beispielantwort

{
  "problem": [
    {
      "level": "SEVERE",
      "description": "8 thread are looping on same lines of code. If threads loop infinitely on the same lines of code, CPU consumption will start to spike up"
    }
  ],
  "threadsRemainingInWaitingState": [
    {
      "method": "java.lang.Object.wait(Native Method)",
      "threadCount": 3,
      "threads": "Reference Handler, Dispatcher-Thread-2, Finalizer"
    },
    {
      "method": "sun.misc.Unsafe.park(Native Method)",
      "threadCount": 2,
      "threads": "New Relic RPM Connection Service, New Relic Retransformer"
    }
  ],
  "threadDumpReport": [
    {
      "timestamp": "2016-03-03 10:37:28",
      "JVMType": " 64-Bit Server VM (23.7-b01 mixed mode)",
      "threadState": [
        {
          "state": "RUNNABLE",
          "threadCount": 28,
          "threads": "Attach Listener, InvoiceGeneratedQC-A99-6, InvoiceGeneratedQC-H87-6, InvoiceGeneratedQC-B85-9, InvoiceGeneratedQC-A99-6, InvoiceGeneratedQC-H87-6, InvoiceGeneratedQC-H87-3, InvoiceGeneratedQC-H87-1, InvoiceGeneratedQC-B85-9, Service Thread, C2 CompilerThread1, C2 CompilerThread0, Signal Dispatcher, main, VM Thread, GC task thread#0 (ParallelGC), GC task thread#1 (ParallelGC), GC task thread#2 (ParallelGC), GC task thread#3 (ParallelGC), GC task thread#4 (ParallelGC), GC task thread#5 (ParallelGC), GC task thread#6 (ParallelGC), GC task thread#7 (ParallelGC), GC task thread#8 (ParallelGC), GC task thread#9 (ParallelGC), GC task thread#10 (ParallelGC), GC task thread#11 (ParallelGC), GC task thread#12 (ParallelGC)"
        },
        {
          "state": "WAITING",
          "threadCount": 6,
          "threads": "Dispatcher-Thread-2, New Relic RPM Connection Service, New Relic Retransformer, Finalizer, Reference Handler, VM Periodic Task Thread"
        },
        {
          "state": "TIMED_WAITING",
          "threadCount": 4,
          "threads": "GC Daemon, New Relic Sampler Service, New Relic Deadlock Detector, New Relic Thread Service"
        }
      ],
      "repeatingStackTrace": [
        {
          "stackTrace": "stacktrace",
          "threadCount": 15,
          "threads": "VM Thread, GC task thread#0 (ParallelGC), GC task thread#1 (ParallelGC), GC task thread#2 (ParallelGC), GC task thread#3 (ParallelGC), GC task thread#4 (ParallelGC), GC task thread#5 (ParallelGC), GC task thread#6 (ParallelGC), GC task thread#7 (ParallelGC), GC task thread#8 (ParallelGC), GC task thread#9 (ParallelGC), GC task thread#10 (ParallelGC), GC task thread#11 (ParallelGC), GC task thread#12 (ParallelGC), VM Periodic Task Thread"
        },
        {
          "stackTrace": "java.lang.Thread.State: RUNNABLE
at com.buggycompany.rt.util.ItinerarySegmentProcessor.setConnectingFlight(ItinerarySegmentProcessor.java:380)
at com.buggycompany.rt.util.ItinerarySegmentProcessor.processTripType0(ItinerarySegmentProcessor.java:366)
at com.buggycompany.rt.util.ItinerarySegmentProcessor.processItineraryByTripType(ItinerarySegmentProcessor.java:254)
at com.buggycompany.rt.util.ItinerarySegmentProcessor.templateMethod(ItinerarySegmentProcessor.java:399)
...",
          "threadCount": 8,
          "threads": "InvoiceGeneratedQC-A99-6, InvoiceGeneratedQC-H87-6, InvoiceGeneratedQC-B85-9, InvoiceGeneratedQC-A99-6, InvoiceGeneratedQC-H87-6, InvoiceGeneratedQC-H87-3, InvoiceGeneratedQC-H87-1, InvoiceGeneratedQC-B85-9"
        },
        {
          "stackTrace": "java.lang.Thread.State: RUNNABLE
",
          "threadCount": 5,
          "threads": "Attach Listener, Service Thread, C2 CompilerThread1, C2 CompilerThread0, Signal Dispatcher"
        },
        {
          "stackTrace": "java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for   (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)
...",
          "threadCount": 3,
          "threads": "New Relic Sampler Service, New Relic Deadlock Detector, New Relic Thread Service"
        },
        {
          "stackTrace": "java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for   (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
...",
          "threadCount": 2,
          "threads": "New Relic RPM Connection Service, New Relic Retransformer"
        },
      ],
      "mostUsedMethod": [
        {
          "method": "com.buggycompany.rt.util.ItinerarySegmentProcessor.setConnectingFlight(ItinerarySegmentProcessor.java:380)",
          "threadCount": 8,
          "threads": "InvoiceGeneratedQC-A99-6, InvoiceGeneratedQC-H87-6, InvoiceGeneratedQC-B85-9, InvoiceGeneratedQC-A99-6, InvoiceGeneratedQC-H87-6, InvoiceGeneratedQC-H87-3, InvoiceGeneratedQC-H87-1, InvoiceGeneratedQC-B85-9"
        },
        {
          "method": "sun.misc.Unsafe.park(Native Method)",
          "threadCount": 5,
          "threads": "New Relic RPM Connection Service, New Relic Sampler Service, New Relic Deadlock Detector, New Relic Thread Service, New Relic Retransformer"
        },
        {
          "method": "java.lang.Object.wait(Native Method)",
          "threadCount": 4,
          "threads": "Dispatcher-Thread-2, GC Daemon, Finalizer, Reference Handler"
        },
      ],
            "threadGroup": [
                {
                    "group": "DQBFacade",
                    "threadCount": 100
                },
                {
                    "group": "SectorwiseContractsFacade",
                    "threadCount": 100
                },
                {
                    "group": "SameDayVoidQC",
                    "threadCount": 100
                },
                {
                    "group": "GC task thread",
                    "threadCount": 13
                },
                {
                    "group": "DefaultQuartzScheduler_Worker",
                    "threadCount": 10
                },
            ],
      "gcThreadsCount": 14
    },
    {
      "timestamp": "2016-03-03 10:37:38",
      "JVMType": " 64-Bit Server VM (23.7-b01 mixed mode)",
      "threadState": [
        {
          "state": "RUNNABLE",
          "threadCount": 28,
          "threads": "Attach Listener, InvoiceGeneratedQC-A99-6, InvoiceGeneratedQC-H87-6, InvoiceGeneratedQC-B85-9, InvoiceGeneratedQC-A99-6, InvoiceGeneratedQC-H87-6, InvoiceGeneratedQC-H87-3, InvoiceGeneratedQC-H87-1, InvoiceGeneratedQC-B85-9, Service Thread, C2 CompilerThread1, C2 CompilerThread0, Signal Dispatcher, main, VM Thread, GC task thread#0 (ParallelGC), GC task thread#1 (ParallelGC), GC task thread#2 (ParallelGC), GC task thread#3 (ParallelGC), GC task thread#4 (ParallelGC), GC task thread#5 (ParallelGC), GC task thread#6 (ParallelGC), GC task thread#7 (ParallelGC), GC task thread#8 (ParallelGC), GC task thread#9 (ParallelGC), GC task thread#10 (ParallelGC), GC task thread#11 (ParallelGC), GC task thread#12 (ParallelGC)"
        },
        {
          "state": "WAITING",
          "threadCount": 6,
          "threads": "Dispatcher-Thread-2, New Relic RPM Connection Service, New Relic Retransformer, Finalizer, Reference Handler, VM Periodic Task Thread"
        },
        {
          "state": "TIMED_WAITING",
          "threadCount": 4,
          "threads": "GC Daemon, New Relic Sampler Service, New Relic Deadlock Detector, New Relic Thread Service"
        }
      ],
      "repeatingStackTrace": [
        {
          "stackTrace": "stacktrace",
          "threadCount": 15,
          "threads": "VM Thread, GC task thread#0 (ParallelGC), GC task thread#1 (ParallelGC), GC task thread#2 (ParallelGC), GC task thread#3 (ParallelGC), GC task thread#4 (ParallelGC), GC task thread#5 (ParallelGC), GC task thread#6 (ParallelGC), GC task thread#7 (ParallelGC), GC task thread#8 (ParallelGC), GC task thread#9 (ParallelGC), GC task thread#10 (ParallelGC), GC task thread#11 (ParallelGC), GC task thread#12 (ParallelGC), VM Periodic Task Thread"
        },
        {
          "stackTrace": "java.lang.Thread.State: RUNNABLE
at com.buggycompany.rt.util.ItinerarySegmentProcessor.setConnectingFlight(ItinerarySegmentProcessor.java:380)
at com.buggycompany.rt.util.ItinerarySegmentProcessor.processTripType0(ItinerarySegmentProcessor.java:366)
at com.buggycompany.rt.util.ItinerarySegmentProcessor.processItineraryByTripType(ItinerarySegmentProcessor.java:254)
at com.buggycompany.rt.util.ItinerarySegmentProcessor.templateMethod(ItinerarySegmentProcessor.java:399)
...",
          "threadCount": 8,
          "threads": "InvoiceGeneratedQC-A99-6, InvoiceGeneratedQC-H87-6, InvoiceGeneratedQC-B85-9, InvoiceGeneratedQC-A99-6, InvoiceGeneratedQC-H87-6, InvoiceGeneratedQC-H87-3, InvoiceGeneratedQC-H87-1, InvoiceGeneratedQC-B85-9"
        },
        {
          "stackTrace": "java.lang.Thread.State: RUNNABLE
",
          "threadCount": 5,
          "threads": "Attach Listener, Service Thread, C2 CompilerThread1, C2 CompilerThread0, Signal Dispatcher"
        },
        {
          "stackTrace": "java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for   (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)
...",
          "threadCount": 3,
          "threads": "New Relic Sampler Service, New Relic Deadlock Detector, New Relic Thread Service"
        },
        {
          "stackTrace": "java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for   (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
...",
          "threadCount": 2,
          "threads": "New Relic RPM Connection Service, New Relic Retransformer"
        },
      ],
      "mostUsedMethod": [
        {
          "method": "com.buggycompany.rt.util.ItinerarySegmentProcessor.setConnectingFlight(ItinerarySegmentProcessor.java:380)",
          "threadCount": 8,
          "threads": "InvoiceGeneratedQC-A99-6, InvoiceGeneratedQC-H87-6, InvoiceGeneratedQC-B85-9, InvoiceGeneratedQC-A99-6, InvoiceGeneratedQC-H87-6, InvoiceGeneratedQC-H87-3, InvoiceGeneratedQC-H87-1, InvoiceGeneratedQC-B85-9"
        },
        {
          "method": "sun.misc.Unsafe.park(Native Method)",
          "threadCount": 5,
          "threads": "New Relic RPM Connection Service, New Relic Sampler Service, New Relic Deadlock Detector, New Relic Thread Service, New Relic Retransformer"
        },
        {
          "method": "java.lang.Object.wait(Native Method)",
          "threadCount": 4,
          "threads": "Dispatcher-Thread-2, GC Daemon, Finalizer, Reference Handler"
        },
      ],
      "gcThreadsCount": 14
    }
  ],
  "responseId": "20161025113858_4"
}

JSON-Antwortelemente

Similar Posts

Leave a Reply

Your email address will not be published.