29.10.2014
Author: Konstantinos Kododimos. K.Kododimos@comundus.com

Tipps zur Liferay Performance-Optimierung

Mit Liferay, einer Open Source Portallösung, werden umfangreiche Enterprise- oder Mitarbeiterportale realisiert. Liferay eignet sich auch für mehrsprachige Internetportale mit geschlossenen Nutzerräumen.
In allen Fällen muss Liferay den Zugriff von mehreren hunderten, gleichzeitigen Zugriffen ohne großen Performance Verlust verkraften.
Leicht gesagt und nicht so einfach zu realisieren. Wir sind an das Thema Liferay Performance systematisch heran gegangen. Heraus gekommen sind allgemeine und Liferay spezifische Regeln, die das Ziel haben eine gute Performance bei hoher Last zu erreichen.

Egal, welche Applikation im Unternehmen im Einsatz ist, ein wesentliches Kriterium für die Akzeptanz bei den Mitarbeitern ist eine gute Performance. Wer lange warten muss bis sich endlich die erste Maske, öffnet bricht ab oder arbeitet lustlos.

 

Laut einer Studie des amerikanischen Optimierungsunternehmens Strangeloop verliert der Betreiber einer Webseite 7% der getätigten Geschäfte bei einer Sekunde mehr Ladezeit. Bei 2 Sekunden ist der Verlust bereits 11% und bei 3 Sekunden gar 16%. Je höher die Ladezeit, desto größer wird die Absprungrate der Seiten-Besucher.

 

http://www.seo2b.de/blog/id-5-tipps-fuer-mobile-seo-im-m-commerce.html

 

Allgemeine Tipps zur Liferay Performance-Optimierung

Lege die Performanceziele am Anfang des Projektes fest.
Für die Definition der Performanceziele sind als erstes folgende Fragen zu klären:

  • Welche Hardware soll zum Einsatz kommen?
  • Wann sind die Spitzenzeiten für die Nutzung der Applikation im Betrieb?
  • Wann treten Dauerbelastungen auf?
  • Welche Schnittstellen zu anderen Systemen wird es geben?

 

Hardware ist endlich

Während der Entwicklung einer Applikation ist zu bedenken, dass Hardware endlich ist. Auch wenn Hardware immer günstiger wird, bedeutet dies nicht, dass während der Programmierung der verfügbare Speicher ignoriert werden sollte bzw. immer wieder aufgestockt werden kann. Eine gute Programmierung spart Speicher.


Erweitere deine Trickliste

Ist die Art wie du deine Anwendungen entwickelst bzw. programmierst noch Up to Date? Die Programmierungswelt verändert sich sehr schnell. Es kommen immer neuere Versionen der verschiedenen Programmierungssprachen auf den Markt. Ebenfalls ändern sich Techniken oder es kommen neue hinzu.
Ergänze dein Repertoire an Tools und schau dich um. Sei offen für neue Tools und bleibe auf dem aktuellen Stand.


Schreibe keinen schlechten Quellcode

Wir haben doch keine Zeit!!! Das Problem der knapp bemessenen Zeit zur Umsetzung einer Anforderung entsteht in den meisten Projekten. Dies sollte aber nicht die Ausrede eines Entwicklers sein. Denn die Zeit, die evtl. durch eine “Quick and Dirty“ geschriebene Funktion/Methode gewonnen wurde, muss in einem späteren Zeitpunkt wieder “refactored“ werden. Nicht nur die Performance des Programms könnte darunter leiden, auch treten Fehler auf, was sicherlich nicht im Sinne des Kunden ist.
Bevor du eine Anforderung umsetzt, nimm dir lieber etwas Zeit, um dir eine gute Lösung für die Umsetzung zu überlegen. Die Zeit wirst du wieder während der Programmierung gewinnen. Halte Konventionen so gut es geht ein. Schreibe für deine Funktionen automatisierte Tests (JUnit), damit du potenzielle Fehler schnell abfangen und korrigieren kannst. Um die Qualität deines Quellcodes zu prüfen, kannst du auch verschiedene Tools wie z.B. SonarQube einsetzen. Solche Tools analysieren den Sourcecode einer Funktion hinsichtlich verschiedener Qualitätsbereiche. Eine andere gute Möglichkeit ist ein Code Review von deinen Kollegen.


Teste dein Programm

Im Rahmen der Tests vor der Auslieferung der Software an den Kunden setzen wir JUnit ein. Somit werden die verschiedenen Funktionen automatisch getestet. Für den Lasttest können verschiedene Webstress-Tools verwendet werden, wie z.B. JMeter – siehe auch http://www.opensourcetesting.org/performance.php.
Wie oben schon beschrieben, sind auch Code-Reviews von höherer Bedeutung.

 

Liferay Performance-Optimierung

Im folgendem werden die Verbesserungsvorschläge erwähnt, die aus Sicht von comundus am wichtigsten erscheinen und die sich aus der langjährigen Projekterfahrung ergeben haben.

Teilweise sind einige dieser Informationen am Buch „Liferay Portal Performance Best Practices“, Autor Samir Bhatt, http://it-ebooks.info/book/2999/, angelehnt. Ebenfalls sind einige der folgenden Informationen unter http://www.liferay.com/de/documentation/liferay-portal/6.1/user-guide/-/ai/performance-tuni-5 zu finden.

 

Liferay Zwiebelmodell

Liferay Portal ist eine Standard Java 2 Enterprise Edition - J2EE-Anwendung. Diese Anwendung wird auf dem Application Server ausgeführt, welche in Java Virtual Machine (JVM) läuft, die wiederum als Standard-Anwendung im Betriebssystem läuft.

Zwiebel

Durch dieses “Zwiebelmodell“ soll deutlich gemacht werden, dass eine evtl. Verbesserung der Liferay Perfomance nicht unbedingt an Liferay vorgenommen werden müsste, sondern an den umliegenden Systemen.

 

Operating System

Auf der Ebene des Betriebssystems könnte ein Prozessor Monitoring vorgenommen werden. Es sollten auch weitere System Ressourcen wie z.B. Arbeitsspeicher, HDD und Netzwerk überprüft werden. Beispielsweise kann in Linux über den Befehl vmstat -t 1 eine tabellarische Auskunft über Prozesse, Arbeitsspeicher, Auslagerung sowie Festplatten- und Prozessor-Aktivitäten ausgegeben werden.

code

 

Ebenfalls können in Linux über den Befehl netstat verschiedene Informationen über den Status der Netzwerkschnittstelle(n) in Erfahrung gebracht werden.

 

Java Virtuell Machine (JVM)

Während die Java Virtual Machine auf einem System läuft, werden verschiedene Java-Objekte erstellt. Einige dieser Objekte, sind langlebig und andere nicht. Dabei gibt es einige Objekte die längere Zeit nicht genutzt werden. Diese sind im Speicher hinterlegt und füllen den Heap Space bis die JVM sich entscheidet, diese zu löschen. Wenn letzteres passiert, dann stoppt der Garbage Collector (GC) alle Prozesse der JVM und schaut im Heap Space nach toten Objekten, um diese zu löschen. Dieser Prozess verlangsamt die Verarbeitung von Anforderung an die JVM.

 

young generation

Die richtige Einstellung in der JVM kann hierbei helfen, die Performance der Anwendung zu verbessern. Standardmäßig nutzt das Java Development Kit (JDK) den Serial Collector. Dieser Collector eignet sich für Desktop basierte Applikationen, die auf einem Prozessor laufen. Für Server basierte Systeme, die auf mehreren Prozessoren laufen, eignet sich der Parallel Collector. Da hierbei Prozesse parallel verarbeitet werden, bietet dieser Collector eine bessere Performance. Es empfiehlt sich den Concurrent Collector zu nutzen, da sich dieser Prozessor Ressourcen teilt und nur kurze Garbage Collection Pausen benötigt.
Neben der richtigen Auswahl des Garbage Collectors, kann durch die richtigen Anpassungen der verschiedenen Heap Bereiche die Dauer der Garbage Collection verringert werden.
Eine Beispielkonfiguration mit den oben genannten Parametern könnte wie folgt aussehen:

code Schnipsel

Application Server

Auf der Ebene des Application Servers können mithilfe des automatischen Protokollierens in eine Logdatei (Log4J) Aktionen und Prozesse identifiziert werden, die zu einer evtl. schlechten Performance einer Anwendung führen könnten.

Des Weiteren können auch verschiedene Profiling Tools oder Monitoring Anwendungen im Application Server eingesetzten werden. Über diese kann das Laufzeitverhalten einer Anwendung und weitere System-Ressourcen überprüft werden, welche die Anwendung nutzt. Hierfür ist das YourKit JavaProfiler und JProfiler zu empfehlen.

 

Datenbank

Viele Performance-Probleme treten auf, weil die Konfigurationen bzw. Einstellungen in der Schnittstelle zur Datenbank oder in der Datenbank selber nicht richtig vorgenommen wurden.

Um die Datenbank Schnittstelle unabhängig von der tatsächlichen Implementierung zu halten, sollte die Schnittstelle über Java Naming and Directory Interface (JNDI) integriert werden.

  • Eine wichtige Einstellung dabei ist, dass die Datenbank connection pool size ungefähr 20 bis 30% der Thread Pool size ausmachen sollte.

 

  • Überprüfe die eingestellten Connections in der JNDI config (root.xml) mit der eurer DB, z.B. JNDI maxActive="750" maxWait="10000„ maxIdle="200" minIdle="30„ und wenn ihr eine MySQL DB nutzt Überprüft in /mysql/my.cnf -> max_connections=750

 

Überprüft auch, auf welche DB Liferay Tabellen Felder deine Anwendung zugreift. Dies kannst du u.a. über eins der oben genannten Profiling Tools analysieren. Wenn du die Felder identifiziert hast, dann setz ein Index auf diese Felder. In Liferay sind nur die primary keys der einzelnen Liferay Tabelle indexiert.

Die …ServiceUtil Klassen von Liferay greifen bei einer Abfrage, z.B. Rollen eines Benutzer, auf die DB zu. Wird solch eine Klasse in einer “for“ Schleife genutzt, entstehen Performanceprobleme. Falls dies in deinem Quellcode der Fall sein sollte, dann suche nach einer besseren Lösung.

Eine bessere Lösung könnte es sein, die Abfrage von Expando Felder über eine Solr Abfrage anstatt über eine “for“ Schleife zu iterieren. Anstatt beispielsweise einzelne JournalArticle auf einem Expando Feld abzufragen, könntest du dieses über eine Solr abfragen und auslesen.


Im folgendem ein kleines Beispiel dazu:

BooleanQuery searchExpando = BooleanQueryFactoryUtil.create(searchContext);

searchExpando.addTerm("expando/custom_fields/changes", "Änderung");

searchExpando.addTerm("expando/custom_fields/changes", "Neu");

this.searchQuery.add(searchExpando, BooleanClauseOccur.MUST);

 

Liferay Portal – Servlet Filter

Schaltet nicht benötigte Servlet Filter aus:

  • AS filter - CAS for Single Sign-On
  • NTLM SSO filter - users authenticating via NTLM
  • OpenSSO filter -  OpenSSO für Single Sign-On
  • SharePoint - functionality for saving documents directly to the portal
  • GZip - compress HTTP responses using GZip compression
  • Strip -  remove blank lines from the generated response
  • ValidHtml - add JavaScript out of the body tag to improve the page rendering performance

 

Liferay Portal – Lucene

Passt die Lucene Indexierung an!
Standardmäßig ist Liferay so konfiguriert, dass bei jedem Commit Indexänderung auf dem Dateisystem vorgenommen werden. Je nach Inhalt können dies große oder viele kleine Dateien sein. Wenn viele Dateien veröffentlicht und geladen  werden müssen, dann passt in der portal-ext.properties folgende Werte an - z.B.
lucene.commit.batch.size=10000    
lucene.commit.batch.size=10000
lucene.commit.time.interval=300000
Der beste Weg ist aber, für die Suche einer seperate Umgebung aufzubauen wie z.B. Solr.

 

Liferay Portal – HTML-Positionierung von Elementen

HTML-Positionierung von Elementen:

Was ist an diesem Code falsch?

code Schnipsel Seite 6

 

Das Javascript hinter dem HTML Code.

In den einzelnen Portlets kann in der liferay-portlet.xml eingestellt werden, wo die JavaScripte liegen sollen:

<footer-portlet-javascript>/html/portlet/message_boards/javascript.js</footer-portlet-javascript>

oder

<header-portlet-javascript>/html/portlet/message_boards/javascript.js</header-portlet-javascript>

 

Résumé

Wie oben schon erwähnt, wurden in diesem Beitrag die Liferay Performance Verbesserungen beschrieben, die aus Sicht von comundus am wichtigsten erscheinen und die sich aus der langjährigen Projekterfahrung heraus ergeben haben.

Weitere Informationen kannst du im Buch „Liferay Portal Performance Best Practices“, Autor Samir Bhatt, finden. Das Buch gibt es auch als Download unter http://it-ebooks.info/book/2999/.