Мониторинг Java-приложений с помощью Health Center API. Часть 1

Начало работы с Health Center API

Health Center версии 2.1 содержит мощный интерфейс прикладных программ (API). Он позволяет Java™-разработчикам внедрять Health Center в свои приложения и использовать его возможности мониторинга для решения разнообразных проблем. Первая часть этой статьи из двух частей учит использовать Health Center API для мониторинга взаимоблокировок при работе Java-приложений. Во второй части к приложению для обнаружения взаимоблокировок, разработанному в этой статье, добавляется представление профилирования методов для определения того, на что приложение расходует большую часть своих процессорных циклов.

Тоби Корбин, программист, IBM

Тоби Корбин (Toby Corbin) - программист, в настоящее время разрабатывает инструментарий RAS в IBM Java Technology Centre. Он поступил на работу в IBM в 2001 году и четыре года занимался разработкой поддержки национальных языков и глобализации для Java Runtime Environment, а затем два года вел разработку библиотек Swing и AWT.



23.05.2013

Сталкивались ли вы когда-нибудь с тем, что сервер приложений зависает без видимых причин или Java-приложение перестает отвечать на запросы? Либо просто плохо работает или расходует слишком много памяти? Health Center упрощает решение подобных проблем.

Мониторинг и диагностика проблем с помощью Health Center

IBM® Monitoring and Diagnostics tools for Java - Health Center (Health Center) ― это бесплатный, необременительный для системы диагностический инструмент и API для мониторинга приложений, работающих на IBM Java virtual machine (JVM). С его помощью можно быстро оценить состояние работающего Java-приложения, получая информацию для выявления и решения проблем. Health Center позволяет:

  • выявить утечку собственной памяти или кучи;
  • узнать, какие методы отнимают больше всего процессорного времени;
  • выявить узкие места в системе ввода-вывода;
  • визуализировать и настроить сбор мусора;
  • обнаружить любые конфликты блокировки;
  • анализировать необычные события WebSphere® в режиме реального времени;
  • контролировать работу потоков приложения;
  • выявлять условия взаимоблокировки;
  • собирать данные для гистограммы классов.

Последняя версия Health Center — это мощный новый API, который можно использовать для написания своих собственных инструментов мониторинга. Теперь дни проблем, трудно поддающихся диагностике и решению, сочтены.

В этой статье показано, как написать инструмент мониторинга, который проверяет приложение на наличие условий взаимоблокировки. Затем те же принципы применяются для написания более глубинных инструментов, позволяющих делать все — от анализа сбора мусора до профилирования методов — и определять, на что приложение тратит свои процессорные циклы.

Требования к системе

Для установки Health Center API требуется, как минимум, Eclipse 3.4 или Eclipse 4.x.

Установка пакета API в Eclipse

Инструменты мониторинга и диагностики IBM обычно устанавливаются в IBM Support Assistant (ISA). Чтобы внедрить Health Center в свое приложение и программировать с помощью API, сначала необходимо установить пакет в среду Eclipse. Для этого выполните следующие действия.

  1. Запустите среду разработки Eclipse.
  2. Выберите Help -> Install New Software (помощь -> установка нового программного обеспечения).
  3. Добавьте узел обновления ISA в качестве нового узла.
    1. Нажмите кнопку Add (добавить).
    2. Укажите в поле имени узел обновления ISA.
    3. В поле расположения введите следующий URL-адрес: http://public.dhe.ibm.com/software/isa/isa410/production/. Это запускает поиск всех имеющихся инструментов, который займет несколько минут.
  4. Введите в поле поиска Health Center.
  5. Выберите пакет Health Center Core Feature и нажмите кнопку Next (см. рисунок 1).
    Рисунок 1. Список программного обеспечения, доступного для установки
    Список программного обеспечения, доступного для установки
  6. Проверьте детали установки и нажмите кнопку Next.
  7. Прочтите и примите условия лицензионного соглашения, затем нажмите кнопку Finish. Это приведет к установке в IDE Eclipse функции Health Center Core. Теперь все готово для программирования с помощью API.
  8. Проверьте параметры установки и нажмите кнопку Next.

Давайте напишем с помощью API простое rcp-приложение для обнаружения условий взаимоблокировки. Сначала создайте новый проект плагина в Eclipse и добавьте в качестве зависимости Health Center API. Для этого выполните следующие действия.

  1. Выберите File -> New -> Project -> Plug-in Project.
  2. Дайте проекту имя, например, HC_Deadlock. Нажмите кнопку Next.
  3. Снимите флажок Generate an activator (создать активатор). На вопрос, хотите ли вы создать rich client-приложение, ответьте Yes. Нажмите кнопку Next (см. рисунок 2).
    Рисунок 2. Параметры проекта плагина
    Параметры проекта плагина
  4. Нажмите кнопку Next. На экране шаблона выберите Headless Hello RCP. Нажмите кнопку Finish.

Затем добавьте в новый проект пакет Health Center API в качестве зависимости. Выполните следующие действия.

  1. Чтобы добавить в манифест импорт API, откройте файл MANIFEST.MF в папке META-INF своего нового проекта (см. рисунок 3).
    Рисунок 3. Плагины Package Explorer
    Плагины Package Explorer
  2. Выберите вкладку Dependencies и нажмите кнопку Add. В области Select а Plug-in введите в поле поиска healthcenter.api. Выберите плагин com.ibm.java.diagnostics.healthcenter.api — обратите внимание, что номер версии может быть другим (см. рисунок 4).
    Рисунок 4. Выбор плагина Health Center API
    Выбор плагина Health Center API
  3. Нажмите кнопку ОК. Повторите последние действия, начиная с выбора вкладки Dependencies. На этот раз добавьте org.eclipse.ui— опять же, номер версии может отличаться (см. рисунок 5).
    Рисунок 5. Выбор плагина org.eclipse.ui
    Выбор плагина org.eclipse.ui
  4. Нажмите кнопку ОК и сохраните файл.

Теперь плагин API включен в приложение, и можно приступать к программированию.


Тестирование приложения на взаимоблокировки

Прежде чем взяться за написание инструмента для контроля взаимоблокировок, нужно иметь, что контролировать. В листинге 1 приведен исходный код простого приложения, которое приводит к взаимоблокировке.

Листинг 1. Простое приложение со взаимоблокировкой
public class GenerateDeadlock {
   AThread t1 = null;
   AThread t2 = null;
   AThread t3 = null;

   static class AThread extends Thread {
      Object hold;
      Object grab;

      AThread(String name, Object hold, Object grab) {
         super(name);
         this.hold = hold;
         this.grab = grab;
      }

      private void delay(long time) {
         try {
            Thread.sleep(time);
         } catch (InterruptedException e) {
         }
      }

      private void grabLocks() {
         System.out.println("Thread " + this + " about to hold " + hold);
         synchronized (hold) {
            System.out.println("  Thread " + this + " about to grab "
                  + grab);
            delay(5000);
            synchronized (grab) {
               System.out.println("    Thread " + this
                     + " got both monitors");
               delay(1000000);
            }
         }
      }

      public void run() {
         System.out.println("Thread " + this + " starting");
         for (int i = 0; i < 200000; i++) {
            grabLocks();
         }
         System.out.println("Thread " + this + " completed");
      }
   }

   private void createDeadlock() {
      System.out.println("Force 3 thread deadlock");
      String s1 = "obj 1";
      String s2 = "obj 2";
      String s3 = "obj 3";
      t1 = new AThread("Thread 1", s1, s2);
      t2 = new AThread("Thread 2", s2, s3);
      t3 = new AThread("Thread 3", s3, s1);
      t1.start();
      t2.start();
      t3.start();
   }

   public static void main(String[] args) {
      GenerateDeadlock d = new GenerateDeadlock();
      d.createDeadlock();
      try {
         Thread.sleep(1000);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
      System.out.println("Press a key to exit");
      try {
         System.in.read();
         System.exit(0);
      } catch (java.io.IOException e) {
      }
   }
}

Health Center состоит из двух частей. Первая часть представляет собой агент Health Center, который загружает контролируемое приложение. Агент предоставляет доступ к данным JVM, которые затем использует вторая часть Health Center —клиент. API предоставляет доступ к этому клиенту, который обычно запускается из ISA. Внедрите клиент в свое приложение, чтобы установить связь с приложением, запущенным агентом Health Center, и получить доступ ко всем данным, которые контролирует и отображает клиент Health Center. API не содержит графического интерфейса; вместо этого все данные становятся доступными в вашем собственном приложении. На рисунке 6 показано расположение клиента и агента Health Center, когда они установлены в ISA и JVM.

Рисунок 6. Расположение клиента и агента Health Center, когда они установлены в ISA и JVM
Расположение клиента и агента Health Center, когда они установлены в ISA и JVM

Запустите программу, приведенную в листинге 1, с подключенным к ней агентом Health Center. Для этого требуется, как минимум, уровень IBM Java 5 SR8, Java 6 SR1 или Java 7. Можно загрузить комплекты IBM для разработчиков.

Чтобы запустить приложение с агентом посредством Java 5 СР10 и выше, Java 6 SR5 и выше или Java 7, используйте следующую команду (см. рисунок 7):

java - Xhealthcenter GenerateDeadlock

Для Java 5 SR9 или более ранней версии или Java 6 SR4 или более ранней версии используйте следующую команду:

java - agentlib:healthcenter - Xtrace:output=healthcenter.out GenerateDeadlock
Рисунок 7. Запуск программы GenerateDeadlock
Запуск программы GenerateDeadlock

Из Java 5 SR9 и Java 6 SR3 агент вводится автоматически. Последние версии агента и инструкции по его обновлению содержатся на странице Health Center - Installing the Health Center agent.


Написание приложения для мониторинга взаимоблокировок

Теперь вы готовы изменить исходное приложение Hello RCP World и превратить его в инструмент обнаружения взаимоблокировок с помощью Health Center API. Откройте файл Application.java (см. рисунок 8).

Рисунок 8. Расположение кода Application.java
Расположение кода Application.java

Настройка параметров соединения

Сначала получите объект ConnectionProperties с параметрами приложения, к которому нужно подключиться. По умолчанию он настроен на использование localhost и порта 1972, но эти значения можно изменить (и добавить защиту) в конструкторе и методах класса:

ConnectionProperties hcConn = new ConnectionProperties();

Когда объект ConnectionProperties получен, подключитесь к приложению, которое нужно контролировать и которое уже запущено агентом Health Center. Вызовите статический метод HealthCenterFactory.connect (hcConn, true). Этот вызов возвращает объект HealthCenter, который представляет собой прямое соединение с Health Center и позволяет получить доступ ко всем данным, контролируемым Health Center. Вызов connect, по существу, запускает экземпляр Health Center в вашем приложении и инициирует сбор данных:

HealthCenter hcMon = HealthCenterFactory.connect(hcConn,true);

Сбор данных

Теперь, когда у вас есть объект HealthCenter, можно выполнить запрос данных. API спланирован аналогично графическому интерфейсу пользователя: сразу после ввода объекта HealthCenter он запрашивает интересующий вас тип данных. В данном случае нужно проверить наличие взаимоблокировок, что можно сделать с помощью класса ThreadsData. Доступ к нему обеспечивает метод getThreadsData() объекта HealthCenter:

ThreadsData hcThreadsData = HealthCenter.getThreadsData();

Класс ThreadsData содержит метод deadlockDetected(), который возвращает значение true, если обнаружена взаимоблокировка. Опрашивая этот метод, можно получать уведомление о возникновении взаимоблокировки:

if(hcThreadsData.deadlockDetected()) {
      do something
}

Доступ к механизму рекомендаций и анализа

Health Center содержит встроенный механизм рекомендаций, который выполняет анализ и возвращает результаты. При запуске полной версии Health Center эти результаты обычно отображаются на панели Analysis and Recommendations (см. рисунок 9).

Рисунок 9. Панель анализа и рекомендаций Health Center
Панель анализа и рекомендаций Health Center

Доступны несколько методов для запроса любых рекомендаций. Метод getAllRecommendations() возвращает массив всех рекомендаций, но можно запросить только критические проблемы, вызвав метод getCriticalRecommendations(), который использует объект ThreadsData.

String[] hcThreadsRec = hcThreadsData.getCriticalRecommendations()

Просмотр полного исходного кода

Предыдущие пять вызовов необходимы для того, чтобы внедрить Health Center в свое приложение и проверить наличие взаимоблокировок в контролируемом приложении. Полный исходный код с этими вызовами показан в листинге 2.

Листинг 2. Полный исходный код, демонстрирующий использование пяти вызовов
package deadlockdemo;

import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;

import com.ibm.java.diagnostics.healthcenter.api.ConnectionProperties;
import com.ibm.java.diagnostics.healthcenter.api.HealthCenter;
import com.ibm.java.diagnostics.healthcenter.api.factory.HealthCenterFactory;
import com.ibm.java.diagnostics.healthcenter.api.threads.ThreadsData;

/**
 * Этот класс управляет всеми аспектами исполнения приложения
 */
public class Application implements IApplication {
   HealthCenter hcMon;

   public Object start(IApplicationContext context) throws Exception {
      ConnectionProperties hcConn = new ConnectionProperties();
      hcMon = HealthCenterFactory.connect(hcConn, true);
      try {
         System.out
               .println("Waiting for 10 seconds to allow initial data to be
                        parsed from the connection");
         Thread.sleep(10000);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
      checkForDeadlock();
      return IApplication.EXIT_OK;
   }

   public void stop() {
      // нечего делать
   }

   public void checkForDeadlock() {
      while (!detectDeadlock()) {
         try {
            Thread.sleep(5000);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }

   private boolean detectDeadlock() {
      ThreadsData hcthreadsData = hcMon.getThreadsData();
      if (hcthreadsData == null) {
         System.out.println("No threads yet");
      } else {
         if (hcthreadsData.deadlockDetected()) {
            Display display = new Display();
            Shell shell = new Shell(display);

            MessageBox mb = new MessageBox(shell);
            String deadlockMessage = new String();
            String[] hcThreadsRec = hcthreadsData
                  .getCriticalRecommendations();
            for (String rec : hcThreadsRec) {
               deadlockMessage = deadlockMessage + rec + "\n";
            }
            mb.setMessage(deadlockMessage);
            mb.setText("Deadlock detected");
            mb.open();
            display.dispose();
            return true;
         }
      }
      return false;
   }
}

Мониторинг взаимоблокировок

Теперь у вас есть приложение для мониторинга взаимоблокировок и программа с взаимоблокировками, работающая в фоновом режиме. Сообщения указывают на наличие взаимоблокировок (см. рисунок 10).

Рисунок 10. Панель результатов с сообщениями о взаимоблокировках
Панель результатов с сообщениями о взаимоблокировках

Заключение

Эта статья содержит основы для начала работы с Health Center API и пример написания инструмента мониторинга, который проверяет приложение на наличие условий взаимоблокировки. Эти методы можно применять для того, чтобы извлекать из Health Center и использовать любые данные. Во второй части мы будем опираться на эти концепции и добавим в приложение для обнаружения взаимоблокировок представление профилирования метода, которое показывает, на что приложение тратит большую часть своих процессорных циклов.

Ресурсы

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Технология Java
ArticleID=931132
ArticleTitle=Мониторинг Java-приложений с помощью Health Center API. Часть 1
publish-date=05232013