JMX - Java Management eXtension im Blick

Der Manager

Dapeng Wang

Früher unter dem Namen JMAPI (Java Management API) bekannt, wurde JMX schon vor einigen Jahren von Sun ins Leben gerufen. Spätestens seit der Verbreitung von J2EE und damit erhöhtem Administrationsbedarf komplexer Java-Anwendungen hat JMX immer mehr an Bedeutung gewonnen und immer mehr Anwender gefunden. Sowohl die führenden kommerziellen J2EE-Anbieter als auch die bekannten Open Source-Projekte wie JBoss haben JMX in ihre Software integriert.

Sie stehen vor dem Problem, das fast in jedem Client-Server-Projekt auftritt: Eigentlich ist alles schon getestet, sodass der Loglevel auf Warn hochgesetzt wird. Es taucht überraschend doch ein Fehler auf und das Lokalisieren des Fehlers ist aufgrund der fehlenden Debug-Informationen extrem schwierig. Daraufhin muss der Server heruntergefahren, der Loglevel in der Properties-Datei auf Debug geändert und der Server wieder hochgefahren werden. Erwünscht ist natürlich, den Loglevel auf der Serverseite zur Laufzeit verändern zu können, aber aus Kostengründen soll dafür nicht extra ein RMI-Server oder sogar EJB programmiert werden, wodurch der Entwicklungs- und Deployaufwand zusätzlich steigen würde.

Bei JMX handelt es sich aber um eine Spezifikation, die Architektur, Design-Patterns, APIs sowie Basisdienste für Anwendungs-, Netzwerk- und Geräteadministration in der Java-Programmiersprache beschreibt. Damit wird ein Framework zur Verfügung gestellt, mit dem Entwickler auf einfache Weise Managementfunktionalitäten in Java implementieren und in ihren Anwendungen integrieren können. Die Integration mit vorhandenen Managementtechnologien wie SNMP (Simple Network Management Protocol), WBEM (Web-Based Enterprise Management) werden ebenfalls in JMX berücksichtigt und teilweise durch zusätzliche JSRs vervollständigt (siehe JSR für SNMP Manager API und JSR-000048 WBEM Services Specification for CIM/WBEM).

Ähnlich wie bei anderen Spezifikationen (beispielsweise JDBC und JNDI) sind nur die Schnittstellen in JMX-Spezifikation beschrieben, die von verschiedenen Herstellern implementiert werden können. Eine Referenzimplementation wurde von Sun zur Verfügung gestellt, die unter java.sun.com/products/JavaManagement/ heruntergeladen werden kann. Ebenfalls steht eine CTS (Compatibility Test Suite) zur Verfügung, die sicherstellt, dass eine Implementation JMX-konform ist.

Abb. 1: JMX-Architektur (Java Management Extensions Instrumentation and Agent Specification)

Die Java-Objekte, die für das Management von Ressourcen zuständig sind, werden als MBeans bezeichnet. Jede MBean implementiert eine Schnittstelle, die bestimmte Design-Patterns (Konventionen ähnlich wie bei JavaBeans) einhalten muss. Diese Schnittstelle pictureet das Management Interface der MBean. Das Management Interface einer MBean besteht aus:

  • Attributen, vergleichbar den Properties von JavaBeans
  • Operationen
  • Notifikationen, die von der MBean gesendet werden können
  • Public-Konstruktoren der MBean-Klasse

JMX hat vier Typen von MBeans definiert:

public class MyFirst implements MyFirstMBean {
private int count = 0;
public int getCount() {
return count;
}

public void setCount(int newCount) {
this.count = newCount;
}

public String getName() {
return "My Counter";
}

public void reset() {
count = 0;
}

public void increment(int step) {
count += step;
}
}

Nachdem eine MBean implementiert ist, muss diese MBean beim MBean-Server des Agenten registriert werden. Damit wird diese MBean für die Managementapplikationen zugänglich gemacht und kann von diesen angesteuert werden. Der MBean-Server ist die Hauptkomponente eines JMX-Agenten und stellt ein Register für die MBeans dar. Alle Managementoperationen von Managementapplikationen erfolgen über das MBeanServer Interface. Jede MBean wird unter einem eindeutigen Objektnamen bei dem MBean-Server registriert. Ein Objektname wird durch die Klasse ObjectName repräsentiert und besteht aus zwei Teilen:

  • Ein Domänenname, der die Managementdomäne bezeichnet
  • Eine Liste von ungeordeneten Key-Property-Paaren

Die String-Darstellung eines Objektnamen sieht folgendermaßen aus:

*:description=Printer z.B. MyDomain:description=Printer, type=laser, vendor=HP und DefautDomain: description=Printer, type=ink

Nachdem die MBeans beim MBean-Server registriert sind, können folgende Operationen über die Schnittstelle des MBean-Servers ausgeführt werden:

  • Alle registrierten MBeans anzeigen
  • Über Query nach MBeans von Objektnamen suchen
  • Attribute einer MBean abfragen oder setzen
  • Operation einer MBean aufrufen
  • Das Management Interface einer MBean untersuchen (Introspection)
  • Sich als Listener bei bestimmten Notifikationen registrieren
  • Neue MBean instanzieren und registrieren

Da die Managementapplikationen meistens in einem anderen Prozess laufen als die zu administrierende Anwendung, müssen die oben genannten Operationen auch remote aufrufbar sein. Dafür sind Protokolladaptoren und Connectoren vorgesehen. Während ein Protokolladaptor die Operationen von MBeans und MBean-Server zur Darstellung eines anderen Protokolls (z.B. SNMP) adaptieren soll, stellt ein Connector Implementationen für protokollspezifische (z.B. RMI) Kommunikation zwischen Managementapplikationen und JMX-Agent zur Verfügung. Obwohl Protokolladaptoren und Connectoren Bestandteile des Agent Levels sind, werden sie aber erst in Zukunft mit Distributed Service Level zusammen spezifiziert.

Auf dem Agent Level sind ebenfalls vier Dienste definiert, die auch als MBeans implementiert werden können:

Abb. 2: Agent View eines HTML-Adaptor

In der Abpictureung 2 ist zu erkennen, dass der JMX-Agent mit der Defaultdomäne JavaMagazin und drei MBeans gestartet ist. Ein Satz ist hier noch über die dritte MBean in der Domäne JMImplementation zu verlieren. Die JMX-Spezifikation schreibt vor, dass jeder MBean-Server eine MBean von der Klasse MBeanServerDelegate unter dem Namen JMImplementation:type=MBeanServerDelegate
zur Verfügung stellen soll, die Auskunft über die JMX-Implementation gibt, in diesem Fall SpecificationVersion und ImplementationVendor.
Beim Klicken auf den Objektnamen von MyFirstMBean wird der Zustand und das Managementinterface von MyFirstMBean dargestellt. Die Getter-Methoden der MBean werden aufgerufen und die Ergebnisse werden neben den Attributen angezeigt. Ebenfalls angezeigt werden andere Metainformationen wie Name, Datentyp und Zugriffsmöglichkeit (RO für Readonly, RW für Read-Write und WO für Write-Only) der Attribute.

Abb. 3: MBean-Anzeige über HTML-Adaptor

Bei beschreibbaren Attributen besteht die Möglichkeit über ein HTML-Eingabefeld den Wert des Attributs direkt zu modifizieren. Beim Drücken auf den Button Apply wird die entsprechende Setter-Methode der MBean mit dem eingegebenen Wert als Parameter aufgerufen. Damit ist man in der Lage, den Zustand der MBean nicht nur zu überwachen, sondern auch zu verändern.

Die Operationen des Managementinterfaces werden ebenfalls in HTML aufgelistet. Beim Drücken auf den entsprechenden Button kann die Operation der MBean aufgerufen werden. Für die Parameter der Operationen werden ebenfalls Eingabefelder zur Verfügung gestellt.

Es ist nicht möglich, Attribute oder Parameter eines beliebigen Datentyps einzugeben; alle primitiven Datentypen aber wie Date, Number und String werden ohne Problem vom HTML-Adaptor unterstützt, sodass viele Anwendungsfälle abgedeckt werden können.

Nun wenden wir uns dem Loglevel-Problem zu, das auch in der Praxis relevant ist. Das Codebeispiel nutzt die Logging-Bibliothek Log4J von Apache [2]. Statt einem Remote-Interface wird zuerst das Managementinterface definiert, das im folgenden Listing beschrieben wird:

import org.apache.log4j.Priority;

public interface LogMBean {
public Priority getPriority(String categoryName);
public void setPriority(String categoryName, String priortiyString) throws PriorityFormatException;
public String displayAllLogSettings();
}

Das Managementinterface enthält drei Operationen:

  • Über getPriority kann der Loglevel einer Kategorie abgefragt werden.
  • Über setPriority kann der Loglevel einer Kategorie verändert werden.
  • displayAllLogSettings zeigt eine Übersicht von den Logleveleinstellungen aller Kategorien an.

Es ist zu erwähnen, dass diese MBean kein Attribut namens priority besitzt, obwohl scheinbar Getter– und Setter-Methoden vorhanden sind. Eine Getter-Methode darf keinen Parameter haben und muss eine Rückgabe vom Typ des Attributs zurückliefern, eine Setter-Methode hat immer nur einen Parameter vom Typ des Attributs und liefert nichts zurück. Daher handelt es sich bei allen drei Methoden um Operationen. Laut der JMX-Spezifikation muss die Implementierungsklasse des LogMBean-Interfaces Log heißen.

import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import org.apache.log4j.Priority;
import org.apache.log4j.Category;
import org.apache.log4j.Hierarchy;

public class Log implements LogMBean {

public Log() {
}

public Priority getPriority(String categoryName) {
Category category = Category.getInstance(categoryName);
Priority prio = category.getChainedPriority();
return prio;
}

public void setPriority(String categoryName, String priortiyString) throws PriorityFormatException {
Category category = Category.getInstance(categoryName);
Priority prio = null;
try {
int priorityInt = Integer.parseInt(priortiyString);
prio = Priority.toPriority(priorityInt);
}catch (NumberFormatException ex) {
prio = Priority.toPriority(priortiyString, null);
}
if(prio!=null)
category.setPriority(prio);
else
throw new PriorityFormatException(priortiyString);
}

public String displayAllLogSettings() {
StringBuffer buffer = new StringBuffer("
");
TreeMap map = new TreeMap();
Enumeration enum = cat.getCurrentCategories();
while (enum.hasMoreElements()) {
Object item = enum.nextElement();
Category cat = (Category)item;
map.put(cat.getName(), cat.getChainedPriority());
}
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Object item = iter.next();
Map.Entry entry = (Map.Entry)item;
buffer.append(entry.getKey());
buffer.append("------>");
buffer.append(entry.getValue());
buffer.append("n");
}
buffer.append("

");
return buffer.toString();
}
}

Weil der Loglevel in der Serverumgebung verändert werden soll, müssen der MBean-Server und die MBeans in demselben Serverprozess laufen. Daher erfolgt sowohl das Starten des MBean-Servers als auch das Registrieren des LogMBean und des HTML-Adaptor in der Serverumgebung. Das geschieht meistens in der Phase, in welcher der Server hochgefahren wird. Weblogic z.B. bietet die Möglichkeit, über eine Startup-Klasse solche Aufgaben zu erledigen.

Über die Browser-Oberfläche ist man nun in der Lage, den Loglevel in der Serverumgebung zur Laufzeit direkt zu manipulieren. Im Vergleich zu der Variante eines RMI-Servers oder einer EJB ist die Entwicklung von MBeans wesentlich einfacher und schneller. Die lästigen Tätigkeiten wie z.B. Stubs generieren, Deployment-Descriptoren erstellen oder RemoteExceptions behandeln fallen weg. JMX stellt in gewisser Hinsicht eine universelle Remote-Schnittstelle zur Verfügung, über die alle Methoden im Managementinterface remote aufgerufen werden können, ohne dass diese Methoden als remote definiert und programmiert sein müssen. Auf der Clientseite ist es auch nicht mehr notwendig, einen spezifischen Client zu programmieren, der bestimmte Remote-Methoden aufruft. Über die Oberfläche der Managementapplikationen (in diesem Fall der Browser-Oberfläche) ist man in der Lage alle Methoden im Managementinterface remote aufzurufen. Insgesamt findet man über JMX schneller und mit wesentlich geringerem Aufwand Zugang in die Serverumgebung und kann Aktionen in dieser ausführen. Andere mögliche Anwendungsszenarien von JMX sind:

  • Lesen und Setzen von Systemproperties zur Laufzeit, sodass z.B. die Verbindung auf einen anderen Server umgelenkt oder die Implementierung eines Interfaces ausgetauscht wird.
  • Überwachen von Speicherverbrauch und ggf. Aktivieren des Garbage-Collectors
  • Anstoßen von Import- oder Exportjobs
  • Leeren des Datencaches

Auch für nicht-administrative Aufgaben kann der Einsatz von JMX sinnvoll sein:

Geschrieben von
Dapeng Wang
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.