Tutorial “Enterprise Service Bus mit Mule ESB”: Steuerung und Kontrolle per JMX

Keine Kommentare

Ist der ESB erst mal produktiv, möchte man vielleicht wissen, was darin so alles vorgeht. Wie bei jedem Server richtet sich der Blick zuerst auf das Log-File. In einen Mule-Server kann man jedoch auch durch andere „Fenster“ hineinschauen: Die Mule Management Console (nur in der Enterprise-Version) oder JMX (auch in der Community-Version). Neben der Überwachung lassen sich per JMX auch Parameter zur Laufzeit ändern. JMX bleibt auch dann weiterhin nützlich wenn man mit der Management Console arbeitet, da sie ebenso einen Zugriff auf die JMX-Beans anbietet.

JMX (Java Management Extension ist bereits seit Version 1.5 in der JVM enthalten. JMX verwaltet sogenannte MBeans, die lesbare und/oder schreibbare Attribute sowie Operationen enthalten können. Das folgende Programm zeigt alle in der JVM existierende MBeans mit ihren Attributen und Operationen an:

public class BeanLister {
    public static void main(String[] args) throws Exception {
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        for (ObjectInstance oi : mbs.queryMBeans(null, null)) {
            System.out.println(oi.getObjectName().toString());
            MBeanInfo info = mbs.getMBeanInfo(oi.getObjectName());
            MBeanAttributeInfo[] attributes = info.getAttributes();
            System.out.println("  attributes:");
            for (int i = 0; i < attributes.length; i++) {
                System.out.println("    " + attributes[i].getName());
            }
            MBeanOperationInfo[] operations = info.getOperations();
            System.out.println("  operations:");
            for (int i = 0; i < operations.length; i++) {
                System.out.println("    " + operations[i].getName());
            }
        }
    }
}

Ist ja ganz nett, wenn man innerhalb eines Java-Programms per JMX in das Java-Programm schauen kann, das ginge jedoch auch einfacher. Wie sieht es aus, wenn wir von draußen in eine JVM schauen wollen? Dafür muss der MBeanServer über eine Remoting-Technologie zugänglich gemacht werden. Dafür gibt es verschiedene Möglichkeiten: Ein Tomcat bietet zum Beispiel eine Web-Schnittstelle an, die sich per Browser bedienen lässt. Ähnliche Schnittstellen bieten auch die gängigen JEE-Server. Serienmäßig – auch ohne EE –  im JDK enthalten ist die Möglichkeit, den MBeanServer per RMI verfügbar zu machen. Das lässt sich sowohl aus dem Programm heraus als auch über die Kommandozeile beim Aufruf der JVM erledigen. Was hilft einem die RMI-Schnittstelle? Muss man sich dafür jetzt extra einen Client schreiben? Nein: Dem JDK liegt mit dem Programm jconsole ein passender Swing-Client bei, hier ein Screenshot:

Screenshot der JMX-Console.

Screenshot der JMX-Console. Links der Baum mit den MBeans, rechts die Attribute einer MBean.

Mit jconsole lassen sich sowohl allgemeine Daten über die JVM anzeigen (über die ersten fünf Tabs) als auch alle MBeans der JVM einzeln ansprechen (im letzten Tab MBeans).

JMX in Mule zugänglich machen

In der Enterprise-Version von Mule ist der Zugriff auf die JMX-Daten über die Management Console möglich, dort muss man sich um nichts kümmern, die nette Web-Oberfläche ist auch recht intuitiv zu bedienen. In der Community-Edition ist ein wenig Arbeit notwendig, dort lässt sich der JMX-Zugriff per RMI einschalten, wenn man folgden Schnipsel in sein XML einbaut:

<management:jmx-server>
    <management:connector-server
        url="service:jmx:rmi:///jndi/rmi://localhost:1099/server"
        rebind="false" />
    <management:credentials>
        <spring:entry key="admin" value="geheim" />
    </management:credentials>
</management:jmx-server>

An der URL erkennt man, dass der Zugriff per RMI läuft. Startet man jconsole, muss man dort genau die gleiche URL eingeben:

Login-Maske von jconsole.

Login-Maske von jconsole.

Wer möchte, kann natürlich einen anderen Port nehmen. Die Verbindung ist in dieser Konfiguration nicht verschlüsselt, eine entsprechende Warnung beim Login in jconsole muss man daher wegklicken. Der Port sollte aber sowieso nicht „von außen“ erreichbar sein, sondern nur im internen (Firmen-)Netzwerk. JMX unterstützt auch eine SSL-Verschlüsselung, auf deren Konfiguration gehe ich hier jedoch nicht weiter ein.

Schaut man sich per jconsole einen Mule-Server an, so sieht man auf der oberen Ebene den Eintrag „Mule.xxx“, wobei „xxx“ der Name der im Server laufenden Mule-Applikation ist. Im folgenden Bild sind einige Knoten aufgeklappt:

Blick per jconsole in einen laufenden Mule-Server.

Blick per jconsole in einen laufenden Mule-Server.

Die wichtigsten MBeans von Mule:

  • Application: Statistik über die gesamte Mule-Applikation.
  • Connector: Alle Konnektoren der Applikation, mit der Möglichkeit, sie anzuhalten und wieder zu starten.
  • Endpoint: Statische Daten zum Endpoint, mit der Möglichkeit, den Endpoint zu deaktivieren (disconnect) bzw. wieder zu aktivieren (connect).
  • Flow: Statistik, aufgeschlüsselt nach Flows der Applikation.

Für eine schnelle Analyse sind die Statistiken schon mal interessant: Die Statistik zeigt, welche Flows wie stark belastet sind und wie die Verarbeitungszeiten aussehen. Die Management Console bietet darüber hinaus noch weitere Möglichkeiten, zum Beispiel eine grafische Aufbereitung oder die Definition von Alerts, so dass man bei Überschreitung von Grenzwerten automatisch benachrichtigt wird (z.B. per SNMP-Trap).

Wer sich das Bild genauer ansieht, entdeckt unten auch die MBean „de.codecentric.jmxdemo“. Sie stammt nicht von Mule, hier wird etwas aus der eigenen Applikation zugänglich gemacht.

Eigene JMX-Beans in Mule

Bevor ich zu der eigenen MBean in Mule komme, brauche ich erst mal eine Beispielanwendung. Sie nutzt wieder meinen „Lieblingsbeispielendpoint“, den File-Endpoint. Er ist halt für eine Demo so schön einfach…

Der Flow nimmt Dateien in einem Verzeichnis entgegen und legt sie – je nach Einstellung zur Laufzeit – links oder rechts ab. Falls man sich weder für links noch für rechts entscheiden kann, gibt es noch einen default-Weg. Grafisch erhält man:

Flow zum Verteilen von Dateien.

Flow zum Verteilen von Dateien.

Von links nach rechts ein File-Endpoint, ein Java-Transformer (der eine Property setzt), ein Logger und der Choice-Router mit den drei möglichen Ausgängen, an denen jeweils ein File-Endpoint für die unterschiedlichen Zielverzeichnisse folgt. In „echten“ Projekten wären das vermutlich eher SOAP, REST oder sonstige Aufrufe an verschiedene Backendsysteme.

Schauen wir uns einige der Teile – vor allem die nicht im Bild sichtbaren – im XML-Format an. Beginnen wir mit der MBean. Die muss man nicht nur implementieren, sie muss auch irgendwie zum Leben erweckt werden. Das heißt, es muss zur Laufzeit eine Instanz erzeugt werden. Am elegantesten geschieht das in Mule durch eine Spring-Bean. Da wir nur eine Instanz benötigen, darf es ein Singleton sein:

<spring:beans>
    <spring:bean id="Control"
                 name="Control"
                 class="de.codecentric.jmxdemo.Control"
                 scope="singleton">
        <spring:property name="direction" value="right" />
    </spring:bean>
</spring:beans>

Der Getter- und Setter im Java-Code sind langweilig, der interessante Teil ist der Konstruktor, in dem sich die MBean selbst beim JMX-Server anmeldet:

public class Control implements ControlMBean {
  private String direction;

  public Control() throws MalformedObjectNameException, InstanceAlreadyExistsException,
                          MBeanRegistrationException, NotCompliantMBeanException {
    MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
    ObjectName name = new ObjectName("de.codecentric.jmxdemo:type=Control");
    try {
      mbs.getObjectInstance(name);
      mbs.unregisterMBean(name);
    } catch (InstanceNotFoundException e) {
      ; // ignore
    }
    mbs.registerMBean(this, name);
  }

  // Getter und Setter fehlen hier.
}

Den try-catch-Block benötigt man wegen des Hot-Deployments in Mule: Der MBeanServer lebt solange wie die JVM. Wird die Applikation zum zweiten mal deployed, so kennt der MBeanServer die MBean bereits, sie muss also erst mit unregisterMBean(…) entfernt werden.

Dieser Teil der Konfiguration macht die MBean bereits in Mule bekannt, so dass wir sie im Flow innerhalb eines Java-Transformers nutzen können:

<flow name="jmxdemoFlow1" doc:name="jmxdemoFlow1">
  <file:inbound-endpoint path="C:\MuleDemo\input" responseTimeout="10000"
                         doc:name="File"
                         moveToDirectory="C:\MuleDemo\processed" />
  <custom-transformer class="de.codecentric.jmxdemo.DirectionSetter"
                      doc:name="DirectionSetter">
    <spring:property name="controller" ref="Control" />
  </custom-transformer>
  <logger level="ERROR" doc:name="Logger"
          message="#['Richtung: ' + message.outboundProperties['direction']]">
  </logger>
  <choice doc:name="Choice">
    <when expression="#[message.outboundProperties['direction']=='left']">
      <file:outbound-endpoint path="C:\MuleDemo\left" responseTimeout="10000"
                              doc:name="left" />
    </when>
    <when expression="#[message.outboundProperties['direction']=='right']">
      <file:outbound-endpoint path="C:\MuleDemo\right" responseTimeout="10000"
                              doc:name="right" />
    </when>
    <otherwise>
    <file:outbound-endpoint path="C:\MuleDemo\output" responseTimeout="10000"
                            doc:name="output" />
    </otherwise>
  </choice>
</flow>

Der Transformer liest aus der MBean die Property „direction“ und setzt sie als Outbound-Property an die Mule-Message. Der Logger und der Choice-Router können anschließend per Mule Expression Language auf die Property in der Message zugreifen und den Wert ausgeben bzw. ihre Routing-Entscheidung davon abhängig machen. Der Vollständigkeit halber hier noch der Java-Code des Transformers:

public class DirectionSetter extends AbstractMessageTransformer {
    private ControlMBean controller;

    @Override
    public Object transformMessage(MuleMessage message, String outputEncoding)
                  throws TransformerException {
        message.setOutboundProperty("direction", controller.getDirection());
        return message;
    }

    public ControlMBean getController() {
        return controller;
    }

    public void setController(ControlMBean controller) {
        this.controller = controller;
    }
}

Was passiert nun, wenn wir die Applikation laufen lassen? Da die „direction“ in der MBean mit „rechts“ vorbelegt ist, werden alle Dateien aus dem Eingangsverzeichnis nach „rechts“ kopiert. Setzt man das Attribut per JMX auf „links“, geht es ab sofort nach „links“. Andere Werte sorgen dafür, dass die Dateien – über den otherwise-Weg des Choice-Routers – im Verzeichnis „output“ landen.

Zusammenfassung

Mule bietet – wie viele Web- oder EE-Server – auch JMX-Unterstützung. Investiert man nicht in die Enterprise-Version mit ihrer Management Console, so muss man auf einen anderen JMX-Client wie jconsole zurückgreifen. Der macht sich zwar nicht so hübsch in einer Vertriebs-Demo, da er doch recht technisch daherkommt, die notwendigen Funktionen sind trotzdem mit wenigen Klicks erreichbar.

JMX bietet nicht nur die Möglichkeit, einen Mule-Server zur Laufzeit ohne ein Blick in das Log zu überwachen, sondern auch die Möglichkeit zur Steuerung. Die Überwachung wäre zwar auch über entsprechende Log-Ausgaben möglich, dadurch würde aber das Log entsprechend länger und man müsste sich die Events dort erst zusammensuchen und Daten berechnen/aggregieren.

Weitere Teile dieser Artikelserie

  1. Was ist ein ESB und wofür kann man ihn nutzen?
  2. Tutorial “Enterprise Service Bus mit Mule ESB”: Hello World/Bus
  3. Tutorial “Enterprise Service Bus mit Mule ESB”: MuleMessage und Java-Komponenten
  4. Tutorial „Enterprise Service Bus mit Mule ESB“: Nachrichten mit Java transformieren
  5. Tutorial „Enterprise Service Bus mit Mule ESB“: Integration von CICS Programmen
  6. Tutorial “Enterprise Service Bus mit Mule ESB”: Transport, Connector, Endpoint: Ein paar Grundlagen…
  7. Tutorial “Enterprise Service Bus mit Mule ESB”: Performance und Threads
  8. Tutorial “Enterprise Service Bus mit Mule ESB”: Steuerung und Kontrolle per JMX
  9. Veröffentlichen von Informationen zu Mule Applikationen im Maven-Umfeld
  10. Tutorial “Enterprise Service Bus mit Mule ESB”: Exceptions und Email

Tags

Roger Butenuth

Dr. Roger Butenuth hat in Karlsruhe Informatik studiert und anschließend in Paderborn promoviert (Kommunikation in Parallelrechnern). Er hat langjährige Erfahrung in der Projekt- und Produktentwicklung.

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.