Как вызвать API анализа дампа потока

В современном мире дампы потоков все еще анализируются в утомительном и ручном режиме, то есть вам нужно связаться с командой DevOps, попросить их прислать вам дампы потоков, затем они пришлют вам дампы потоков по почте, после чего вы загрузите дампы в инструмент анализа дампа потока, тогда вам придется применить свой интеллект, чтобы проанализировать его. Не существует программного способа для упреждающего анализа дампов потоков. Таким образом, чтобы устранить эту проблему, fastthread.io представляет RESTful API для анализа дампов потоков. С помощью одной строки команды CURL вы можете мгновенно проанализировать дампы потоков.

Вот несколько вариантов использования, в которых этот API может быть чрезвычайно полезен.

Пример использования 1. Автоматический анализ первопричин

Большинство DevOps использует простые инструменты Http ping или APM для мониторинга работоспособности приложений. Этот пинг хорош для определения того, живо приложение или нет. Инструменты APM отлично информируют о том, что процессор приложения увеличился на «x%», использование памяти увеличилось на «y%», время отклика сократилось на «z» миллисекунд. Он не будет сообщать, что вызвало всплеск загрузки ЦП, что привело к увеличению использования памяти, что привело к ухудшению времени отклика. Если вы можете настроить задание Cron для сбора дампов потоков/журналов сборщика мусора с периодическим интервалом и вызывать наш REST API, мы применяем наши интеллектуальные шаблоны и алгоритмы машинного обучения для мгновенного определения основной причины проблемы.

Преимущество 1: Всякий раз, когда возникают подобные производственные проблемы, команда DevOps перезапускает серверы, не сохраняя дампы потоков и журналы сборщика мусора. Вам необходимо захватить дампы потоков и журналы GC в тот момент, когда возникает проблема, чтобы диагностировать проблему. В этой новой стратегии вам не нужно об этом беспокоиться, потому что ваше задание cron периодически собирает дампы потоков/журналы GC и вызывает REST API, все ваши дампы потоков/журналы GC архивируются на наших серверах.

Преимущество 2: В отличие от инструментов APM, которые утверждают, что добавляют менее 3% накладных расходов, тогда как на самом деле они добавляют несколько сгибов, красота этой стратегии заключается в следующем: она не добавляет никаких накладных расходов (или незначительных накладных расходов). Потому что весь анализ дампов потоков/GCeasy выполняется на наших серверах, а не на ваших производственных серверах.

Вариант использования 2: тесты производительности

При проведении тестов производительности может потребоваться периодическое получение дампов потоков/журналов сборщика мусора и их анализ через API. В случае, если количество потоков превышает пороговое значение, или если слишком много потоков находятся в ОЖИДАНИИ, или если какие-либо потоки БЛОКИРОВАНЫ в течение длительного периода, или блокировка не снимается, или происходят частые действия полного GC, или время паузы GC превышает пороговые значения, необходимо получить видимость прямо здесь и сейчас. Его следует проанализировать до того, как код попадет в производство. В таком случае этот API станет очень удобным.

Вариант использования 3: Непрерывная интеграция

В рамках непрерывной интеграции настоятельно рекомендуется выполнять тесты производительности. Дампы потоков/журналы сборщика мусора должны быть захвачены и могут быть проанализированы с помощью API. Если API сообщает о каких-либо проблемах, сборка может завершиться ошибкой. Таким образом, вы можете обнаружить падение производительности прямо во время фиксации кода, а не в лабораториях производительности или в рабочей среде.

Как вызвать API анализа дампа потока?

Вызов API анализа дампа потока очень прост:

1.) регистр с нами. Мы вышлем вам ключ API по электронной почте. Это одноразовый процесс настройки. Примечание: если вы приобрели корпоративная версия с API, вам не нужно регистрироваться. Ключ API будет предоставлен вам как часть инструкции по установке.
2.) Отправьте HTTP-запрос на
3.) Тело HTTP-запроса должно содержать дамп потока, который необходимо проанализировать. Вы можете отправить 1 дамп потока или несколько дампов потока в одном запросе.
4.) Ответ HTTP будет отправлен обратно в формате JSON. JSON имеет несколько важных статистических данных о дампе потока. Основным элементом ответа JSON является: «проблема». API применяет несколько интеллектуальных шаблонов анализа дампа потока, и если он обнаружит какие-либо проблемы, об этом будет сообщено в этом элементе «проблема».

СВЕРНУТЬ команду
Предполагая, что ваш файл дампа потока находится в «./my-thread-dump.txt», тогда команда CURL для вызова API:

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

Это не может быть проще, чем это? Не так ли?

Сжатие
Thread Dump имеют довольно большой размер. Для быстрой и эффективной обработки мы рекомендуем вам сжимать и отправлять файлы дампа потока. Когда вы сжимаете дамп потока, вам необходимо передать элемент «Content-Encoding» в элементе заголовка HTTP или в параметре URL.

Скажем, предположим, что вы сжимаете файл дампа потока в формат «zip», тогда вы можете вызывать API с элементом заголовка HTTP.

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

или вы также можете вызвать API с элементом Content-Encoding в параметре URL

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

Мы поддерживаем следующие форматы сжатия:

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

Вы можете использовать тот, который вам нравится. Какой бы формат сжатия вы ни использовали для сжатия дампа кучи, он должен быть передан в элементе Content-Encoding.

Другие инструменты
Вы также можете вызывать API с помощью любых клиентских инструментов веб-сервиса, таких как: пользовательский интерфейс SOAP, плагин для браузера Postman и т. д.

почтальон-ft.png
Рис. Отправка дампов потоков с помощью плагина PostMan

Пример ответа

{
  "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

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *