Статьи

Выявление JVM — сложнее, чем ожидалось

В  Plumbr  мы провели последний месяц, создавая основу для будущих серьезных улучшений. Одним из таких строительных блоков было добавление уникального идентификатора для JVM, чтобы связать все сеансы из одной JVM вместе.

Хотя вначале это кажется тривиальной задачей, сложности, связанные с этой проблемой, начинают поднимать свои уродливые головы, когда смотрят на вывод команды jps, связанной с JVM, в  которой  перечислены все запущенные в настоящий момент процессы Java на моем компьютере:

My Precious:tmp my$ jps
1277 start.jar
1318 Jps
1166

Выше приведен вывод команды jps, в  которой  перечислены все запущенные в настоящий момент процессы Java на моем компьютере. Если вы не знакомы с инструментом — в нем перечисляются все идентификаторы процессов в левой части и имя процесса в правой колонке. Видимо, единственное, кто потрудился перечислить себя под значимым именем, это сам  jps  . Другие два не так вежливы. За аббревиатурой start.jar скрывается экземпляр Jetty, а полностью анонимный — фактически Eclipse. Я имею в виду, действительно — самая большая IDE в мире Java не может даже перечислить себя под именем в стандартных инструментах Java?

Итак, имея представление о современном состоянии встроенных инструментов, давайте вернемся к нашим требованиям. Наше текущее решение идентифицирует JVM по комбинации ID процесса и имени машины. У этого есть один очевидный недостаток — всякий раз, когда процесс умирает, его реинкарнация не будет получать тот же идентификатор от ядра. Поэтому всякий раз, когда JVM  Plumbr  осуществлял мониторинг, перезапускался или убивался , мы теряли трек и не могли связать последующие вызовы вместе. Очевидно, что это не разумное поведение для инструмента мониторинга, поэтому мы пошли дальше, чтобы найти лучшее решение.

Следующий очевидный шаг был сделан три месяца назад, когда мы разрешили нашим пользователям указывать имя машины через   параметр запуска -Dplumbr.application.name = my -ious-jvm . Как это ни странно и мудро, в течение этих трех месяцев только 2% наших пользователей пытались указать этот параметр. Итак, пришло время вернуться к чертежной доске и посмотреть, какие опции у нас есть, когда мы пытаемся  автоматически привязать уникальный и читаемый человеком идентификатор к экземпляру JVM .

Наш первый подход состоял в том, чтобы получить имя класса с помощью  метода main ()  и использовать его в качестве идентификатора. Непосредственные недостатки были сразу заметны, когда мы запустили сборку в блоке разработки, содержащую четыре разных экземпляра Jetty — сразу же у вас было четыре разных JVM, каждый из которых связывал себя одним и тем же не столь уникальным идентификатором.

Следующая попытка состояла в том, чтобы проанализировать содержимое приложения и идентифицировать приложение из дескрипторов развертывания — в конце концов, большинство приложений, отслеживаемых  Plumbr  , упакованы в пакеты WAR / EAR, поэтому было бы целесообразно использовать информацию, присутствующую в комплекте. , И действительно, подавляющее большинство инженеров действительно дали значимые имена в параметре  <display-name>  внутри  web.xml  или  application.xml .

Это решило часть проблемы — когда все эти четыре экземпляра Jetty запускают приложения с разными <display-name> , они будут выглядеть как уникальные. И действительно, до тех пор, пока наша среда не показала, что это не всегда так. У нас было несколько разных экземпляров Plumbr Server на одном компьютере, на которых использовались разные серверы приложений, но был развернут один и тот же файл WAR с одним и тем же параметром <display-name>. Как вы можете догадаться, это снова убивает уникальность такого идентификатора.

Еще одна проблема была связана с тем, что на серверах приложений работают несколько веб-приложений. Что произойдет, если вы развернете несколько файлов WAR в свой контейнер?

Поэтому нам пришлось копать дальше. Чтобы различать несколько JVM, выполняющих одно и то же приложение на одном компьютере, мы добавили папку запуска, чтобы гарантировать уникальность идентификатора. Но проблема нескольких WAR все еще сохранялась. Для этого мы вернулись к нашей первоначальной гипотезе, в которой мы использовали имя основного класса в качестве идентификатора.

Помимо некоторых технических нюансов, таких как различие между фактическим хешем, используемым для идентификатора, и удобной для пользователя версией того же хеша — теперь у нас есть решение, которое покажет вам нечто похожее в списке ваших отслеживаемых JVM:

Машина JVM С тех пор
artemis.staging Самообслуживание (ВОЙНА) 07.07.2014 11:45
artemis.staging Интернет-магазин (WAR) 08.07.2014 18:30
aramis.live com.ringbearer.BatchProcessor 01.01.2001 00:00

Таким образом, мы смогли найти достойное решение и вернуться к ручному именованию с   параметром -Dplumbr.application.name, если ничего не получится . Остается один вопрос — почему системным администраторам так часто не хватает чего-то такого в инструментах и ​​API-интерфейсах JVM?