Tuning-Tipps für Applikations-Server

06.10.2006
Wie Unternehmen mit J2EE-Plattformen robuste Anwendungen bauen können.
Bei diesem Internet-Shop werden die einzelnen Mandanten innerhalb getrennter JBoss-Instanzen betrieben. Sie haben Zugriff auf eine separate Datenbank. Die Server laufen im Cluster, so dass durch Session-Replikation sichergestellt ist, dass alle Instanzen eines Mandanten über die gleichen Sitzungsinformationen verfügen. Die Lastverteilung der HTTP-Requests erfolgt mit Hilfe des Apache-Moduls "jk_mod".
Bei diesem Internet-Shop werden die einzelnen Mandanten innerhalb getrennter JBoss-Instanzen betrieben. Sie haben Zugriff auf eine separate Datenbank. Die Server laufen im Cluster, so dass durch Session-Replikation sichergestellt ist, dass alle Instanzen eines Mandanten über die gleichen Sitzungsinformationen verfügen. Die Lastverteilung der HTTP-Requests erfolgt mit Hilfe des Apache-Moduls "jk_mod".

Architekturen für verteilte Anwendungen strukturieren viele Firmen komponentenorientiert mit der J2EE-Plattform. Der Standard enthält die Spezifikation Enterprise Javabeans (EJB), mit der sich Server-seitige Softwarekomponenten entwickeln lassen. Dabei sind einige Punkte zu beachten.

Was Sie beachten sollten

• Nutzung von robusten, optimierbaren Datenbankzugriffs-Schnittstellen;

• wenn möglich auf verteilte Transaktionen verzichten;

• die Transaktionsverarbeitung sollte einfach programmiert sein (eine Transaktion je Client-Request);

• zustandslose Komponenten verwenden, die sich einfach auf Cluster verteilen lassen;

• Verteilung von Enterprise Javabeans einer Anwendung auf heterogene EJB-Container vermeiden;

• vor allem bei großen Anwendungen sollte man nicht auf Container-Managed Persistence zurückgreifen;

• keine Veränderung der EAR-Dateien bei der Inbetriebnahme (besser ist hier die Konfiguration über eine Datenbank);

• mandantenspezifische Beans in eigenen EJB-Containern ablaufen lassen.

Fazit

• Anwender sollten bereits bei der Architekturgestaltung einer Anwendung und bei der Programmierung auf Robustheit achten. Das bedeutet, möglichst zustandslose Session-Beans einzusetzen.

• Insbesondere beim Zugriff auf große Datenbanken und bei der Transaktionensverarbeitung kann man sich nicht unbedingt auf die Applikations-Server-Produkte verlassen.

• Eigene Datenbankzugriffsschichten auf Basis von Bean-managed Persistence (BMP) und Java Database Connectivity (JDBC) sind auch bei EJB 3.0 immer noch leichter zu optimieren und vereinfachen zudem die Fehlersuche.

• Bei Transaktionen sollte man den Einsatz von Container-managed Persistence (CMP) lieber vermeiden.

Hier lesen Sie …

Mehr zum Thema

www.computerwoche.de/

577524: Jboss bringt Web-2.0-Framework;

577208: Java öffnet sich für SOA;

1214574: Bea öffnet Persistenz-Engine;

576158: Oracle födert Ajax und Java;

578388: SAP-Host- Integration.

Glossar

BMT: Bean Managed Transaction, Bean-Entwickler programmiert die Transaktionsgrenzen selbst.

BMP: Bean Managed Persistence, Entity Bean, bei der der Bean-Entwickler für die Persistierung zuständig ist.

CCM: Sprachunabhängiger Komponentenstandard der Object Management Group. CCM = CORBA Component Model.

Container: Ablaufumgebung für Enterprise Javabeans innerhalb des Applikations-Servers.

DD: Deployment Descriptor.

CMP: Container Managed Persistence, Entity Bean, bei der der Container die Persistierung übernimmt.

CMT: Container Managed Transactions, Container übernimmt im Gegensatz zu BMT die Markierung der Transaktionen.

EAR: Enterprise Archive.

EJB: Enterprise Java Bean, serverseitige Komponententechnologie.

JCP: Java Community Process, dient der "offenen" Weiterentwicklung von Java-Technologien.

JDBC: Java Database Connectivity API für den Zugriff auf relationale Datenbanken über SQL.

JDO: Java Data Objects, ein Object-Relational-Mapping-Standard für Java, der aber nicht so häufig verwendet wird.

JMS: Java Messaging Service, Messaging-API, die von Applikations-Servern unterstützt wird, JMS unterstützt das Peer-to-Peer und das Publish-Subscribe-Modell sowie transiente und persistente Kommunikation.

JTA: Java Transaction API zum Programmieren von Transaktionen.

J2EE: Java 2 Platform Enterprise Edition, Java-Spezifikation (liegt in Version 5 vor) mit vielen Standard-APIs für die serverseitige Entwicklung, dazu gehören EJB, JMS, JSP, Servlets, JTA, JNDI, JDBC und JAX-RPC.

Entity Bean: Mechanismus zur Implementierung von Geschäftsobjekten.

MDB: Message-Driven Bean, dient zum Bearbeiten von Nachrichten, die über JMS an eine Bean gesendet werden bzw. zum Senden von Nachrichten aus einer EJB heraus. MDBs besitzen kein Interface für Clients, die Kommunikation mit Partnern erfolgt über JMS.

Session Bean: Mechanismus man zur Implementierung von Geschäftsprozessen. Man unterscheidet stateless und stateful Session Beans.

2PC-Protokoll: Two-Phase-Commit, ein Koordinationsprotokoll für verteilte Transaktionen.

XA: Die Standardschnittstelle zwischen Ressourcen-Managern (Datenbanken) und Transaktions-Managern der Open Group zur Koordination verteilter Transaktionen. Diese API wird heute von allen Datenbank- und Applikations-Server-Herstellern unterstützt.

Datenbankzugriffe

Wer verteilte Anwendungen entwickelt, muss vor allem auf die Datenhaltung und den Zugriff auf Daten berücksichtigen. Für die persistente Datenhaltung sieht der EJB-Standard zwei Mechanismen vor: Container-Managed Persistence (CMP) folgt dem Konzept des Object Relational Mapping. CMP verknüpft in einem EJB-Con- tainer Java-Objekte mit Tabel- leneinträgen einer relationalen Datenbank. Der Entwickler muss Datenbankzugriffe nicht in SQL formulieren, sondern kann Relationen und Zugriffe ent- weder über Java-Annotationen direkt im Code oder in einem Deployment Descriptor in einer eigenen Sprache (EJB-QL) formulieren. Der Container erle- digt zur Laufzeit die Datenbankzugriffe.

Alternativ dazu lassen sich in EJB Datenbankabfragen manuell programmieren. Bei dieser Vorgehensweise, die als Beans Managed Persistence (BMP) bezeichnet wird, programmiert ein Entwickler alle SQL-Statements in den Komponenten.

Aufgrund der noch nicht ausgereiften Mechanismen in EJB 2.1 ist CMP erst ab EJB 3.0 zu empfehlen, und selbst dann nur für kleinere Datenbanken. Bei größeren Datenbanken ist es aufwändig, CMP einzurichten. Zudem bietet die Methode wenige Möglichkeiten, um Datenbankzugriffe effizient zu gestalten, da man die SQL-Anweisungen nicht unmittelbar beeinflussen kann. Bei Leistungsengpässen kann dies zu Problemen führen. Daher sollten Anwender auf CMP (noch) verzichten, auch wenn es als eines der wichtigsten Features von EJB angepriesen wird. Stattdessen sollte man selbst eine Persistenzschicht entwickeln.

Behandlung von Transaktionen

Eine ähnliche Situation liegt bei der Transaktionsunterstützung vor. Auch hier sind im EJB-Standard zwei Varianten vorgesehen: Container Managed Transactions (CMT) und Beans Managed Transactions (BMT). Ähnlich wie bei den Datenbankzugriffen übernimmt bei CMT der EJB-Container die Transaktionssteuerung und bei BMT der Bean-Entwickler.

Bei CMT wird jede Methode mit einem Transaktionsattribut (in EJB 3.0 über Annotationen) beschrieben. Der Parameter gibt an, wie die Java-Methode in eine Transaktion einzubinden ist. Anwender sollten die Attributvergabe einheitlich gestalten, indem sie das Attribut "Required" in allen Methoden setzen. Bei dieser Variante wird jeder Methodenaufruf innerhalb einer Transaktion ausgeführt. Dies mag zwar etwas auf die Leistung drücken, ist aber leichter nachzuvollziehen als eine Mischung verschiedener Transaktionsattribute in einer Anwendung.

Container-managed Trans- aktionen sind jedoch mit Vorsicht zu genießen. Robuster ist die BMT-Variante. Bei nur ei- ner Datenbank ist BMT sinnvoller.

Implementierungsfragen

Für BMT gibt es zwei Realisierungsvarianten. Entweder programmiert der Softwareexperte eine direkte Transaktionskontrolle über die Datenbankmechanismen oder er nutzt das für die Transaktionssteuerung vorgesehene Java Transaction API (JTA) zur Angabe der Transaktionsgrenzen. JTA ist notwendig, wenn man mehrere Datenbanken innerhalb einer Transaktion bedienen muss.

Zwar könnte auch ein EJB-Client die Transaktionsgrenzen setzen. Dies sollte aber vermieden werden. Der Grund: Stürzt der Client während der Transaktionsverarbeitung ab, hat der Server Probleme, den Vorgang zurückzusetzen. Eine Transaktion sollte daher immer im Server beginnen und enden. Nicht empfehlenswert sind Transaktionen, die mehr als eine entfernte Methode aufrufen. Der Rat lautet hier, eine abgeschlossene Transaktion pro Client-Request (entfernter Methodenaufruf). Dies mag kein perfekter Ansatz sein, vermeidet aber einige Schwierigkeiten beim Wideranlauf nach Fehlersituationen. Werden Daten über mehrere Client-Requests bearbeitet, sollte in der Anwendung ein optimistisches Sperren über Datenbanktransaktionen hinweg realisiert werden. Vor jeder Änderung eines Datenbankobjekts muss im Server abgefragt werden, ob es sich seit dem letzten Lesezugriff verändert hat.

Verteilte Transaktionen über EJB-Container-Grenzen hinweg sind ohnehin zu vermeiden, da ein dafür nötiges Two-Phase-Commit-Protokoll (kurz 2PC) im Fehlerfall zu Schwierigkeiten führen kann. Übergreifende Transaktionen über Container verschiedener Hersteller hinweg sind kaum zu realisieren, da es keine Standards für 2PC gibt.

Deployment und Konfiguration

In der Praxis wird häufig die Frage gestellt, wie man EJB-Anwendungen konfiguriert und verteilt (Deployment). EJB-Applikationen an verschiedene Systemumgebungen anzupassen ist selten trivial. Hinzu kommt, dass der Betreiber einer EJB-Anwendung nicht unbedingt das Know-how besitzt, um selbstständig bestehende Enterprise-Archive-Dateien (EAR) zu konfigurieren. Außerdem zieht zum Beispiel die Änderung eines Deployment Deskriptors immer ein erneutes Deployment der Anwendung nach sich, was operative Risiken in sich birgt. Ganz abgesehen davon ist aus Gründen der Qualitätssicherung eine Manipulation einer einmal installierten und getesteten EAR-Datei häufig nicht erwünscht.

Komfortabler ist hier eine Lösung, bei der eine einmal ausgelieferte EAR-Datei direkt auf unterschiedlichen Systemumgebungen installiert werden kann. Neben dem EAR-File weitere Konfigurationsdateien zu verwenden führt meist zu Problemen, da der Dateizugriff auf solche Files sowie die Festlegung ihres Speicherorts innerhalb des Applikations-Servers nicht standardisiert ist. Bei umfangreicheren Anwendungen hat es sich bewährt, die gesamte Konfiguration in eine Datenbank auszulagern. Somit muss im Idealfall nur die "Datasource" konfiguriert werden, was außerhalb der EJB-Anwendung erfolgen kann. Ein weiterer Vorteil: Umgebungen lassen sich dynamisch konfigurieren, und ein erneutes Deployment erfordert keinen Neustart.

Konfigurationsschnittstellen

Ebenfalls empfehlenswert ist es, EJB-Anwendungen von Beginn an mit eigenen Konfigurationsschnittstellen auszustatten, die sich zum Beispiel über Web-Services und einfache Web-Frontends aufrufe lassen. Hierzu können Entwickler auf ausgereifte Basistechniken wie zum Beispiel JMX zurückgreifen.

Für kleinere Umgebungen beziehungsweise Systeme, die keine Datenbank verwenden, kann auch die Konfiguration über die Systemvariablen des Containers (System Properties) erfolgen. Da diese jedoch für den ganzen Container gelten, ist darauf zu achten, dass es hier nicht zu Konflikten mit anderen Anwendungen kommt.

Mandantenfähige Anwendungen

Eine genaue Planung erfordert es auch, wenn Anwender mehrere Instanzen einer EJB-Applikation parallel betreiben möchten. Dies ist zum Beispiel von Belang, wenn ein mandantenfähiges System zu realisieren oder verschiedene Entwicklungsstände in Produktion zu bringen sind. Anwender müssen klären, wie einzelne Instanzen voneinander getrennt werden können. Der Grund: Es ist nicht einheitlich geregelt, welche reale Ablaufumgebung ein Server für Anwendungen eines Containers zur Verfügung stellt.

Mehrere Instanzen

Betreibt man mehrere Instanzen einer Anwendung innerhalb eines Containers, so ist darauf zu achten, dass diese durch individuelle JNDI-Namen (Java Naming and Directory Interface) sauber voneinander getrennt werden. Andernfalls können sich die Softwareroutinen beim Zugriff auf Bibliotheken gegenseitig stören. Laufen wie im Falle des Java-Servers Jboss alle Anwendungen in einer virtuellen Java-Maschine, so muss das Class-Loading unter Umständen besonders konfiguriert werden. Änderungen bei den Einstellungen sowie der Neustart beeinflussen somit alle Instanzen. In vielen Fällen empfiehlt es sich daher, mehrere vollkommen getrennte Container zu verwenden, zum Beispiel indem man mehrere Instanzen des kompletten Applikations-Servers betreibt. Der Vorteil dabei ist, dass damit die Prozesse auf der Ebene des Betriebssystems vollkommen voneinander getrennt sind und jeder für sich einen überschaubaren Bedarf an System-Ressourcen beansprucht. Dieses Vorgehen führt natürlich zu einem Overhead durch redundant betriebene Serverprozesse.

Performance und Skalierbarkeit

Leistungsmessungen haben ergeben, dass Applikations-Server heute keinen Engpass mehr darstellen. Die Produkte können problemlos mit entsprechender Rechnerausstattung eine große Zahl von Benutzern bedienen. Gängige EJB-Produkte unterstützen Cluster-Funktionen, so dass mehrere Rechner im Verbund nutzbar sind. Doch typischerweise nutzen Firmen für Projekte einzelne, leistungsfähige Maschinen und ziehen die Cluster-Option - wenn überhaupt - oft erst später in Betracht. Allerdings sind Konfiguration und Betrieb eines umfangreichen Cluster-Systems auch nicht zu unterschätzen. Fällt ein Container aus, sind davon alle darin ablaufenden Beans betroffen. Anwendungen sind daher so zu konzipieren, dass sie sich leicht auf einen anderen Container portieren lassen.

Eine Architektur wird durch Cluster skalierbar, darf aber nicht abhängig davon sein. Auch aus diesem Grund sollten Unternehmen verteilte Transaktionen vermeiden. Und die sind auch gar nicht notwenig: Gerade Service-orientierte Architekturen kommen gut mit individuellen, voneinander getrennten Transaktionen aus, so dass die Komplexität einer verteilten Transaktionsverarbeitung in der Regel nicht gerechtfertigt ist.

Ferner ist es ratsam, sitzungsbezogenen Informationen überschaubar zu halten. Der Grund: Bei Verlust dieser Angaben muss der Client schnell wieder in einen konsistenten Zustand kommen, zum Beispiel mit Hilfe einer Datenbank. Beherzigen Firmen diese Regeln, so kann der Umstieg auf eine hochskalierbare Cluster-Umgebung reibungslos und gefahrlos erfolgen.

Wie geht es weiter mit EJB?

Die J2EE/EJB-Technik gibt es nun schon bald zehn Jahre, und sie ist mittlerweile bei der Version 3.0 angelangt. J2EE und EJB werden vom Java-Community-Prozesses (JCP) ständig verbessert und erweitert. Die Weiterentwicklung scheint für die nächsten Jahre garantiert zu sein.

Weiterentwicklung

Ein Umstieg von EJB 2.1 auf EJB 3.0 ist relativ problemlos möglich, da die alten Mechanismen noch funktionieren. Trotzdem sollten Firmen erst einmal abwarten, bis die Hersteller stabile Lösungen vorweisen können, bevor sie neue EJB-Features einführen.

Auch die Applikations-Server-Hersteller binden neue Verfahren ein. Web-Service-APIs sind beispielsweise weitgehend fester Bestandteil aller Produkte. Hier sind Anwender aber gut beraten, darauf zu achten, dass Implementierungen dem WS-I-Standard (Web-Services Interoperability) folgen. (fn)