Liferay Performance im Zusammenhang mit dem Liferay-Asset-Publisher

von Peter Soth

In diesem Blog-Post möchte ich über ein aktuelles Projekt berichten, in dem wir die ungenügende Performance eines Liferay Portals für einen Kunden untersuchten. Die Geschwindigkeit einer Web-Page muss immer auf der Client- sowie Server-Seite betrachtet werden.

Aspekte auf der Client-Seite:

Im Browser sind hierbei folgende Punkte zu untersuchen:

  • Wird GZIP benutzt?
  • Sind die JavaScript und CSS-Dateien minifiziert?
  • Werden riesige Fotos benutzt? Viele Bilder lassen sich durch den Gebrauch eines professionellen Tools, wie PhotoShop beträchtlich komprimieren. Auch ist es sinnvoll zu überprüfen, ob Bilder in der passenden Größe übertragen werden. Ein Bild, das eine Auflösung von 4000 Pixeln hat, von dem aber mittels img-Tag nur 100 Pixel gebraucht werden, ist Verschwendung
  • Wie viele Files sind herunterzuladen? Der Einsatz von Sprite-Grafiken oder durch das Zusammenfügen mehrerer kleiner Dateien, in eine umfassende, reduziert die Anzahl der Dateien, die zu laden sind.
  • Wo sind die JavaScript Dateien eingefügt? Es gilt zu überprüfen, welche JavaScript-Dateien am Ende der HTML-Seite platziert werden können, damit Sie erst, wenn die Seite aufgebaut ist, geparst und somit verarbeitet werden.  
  • Nützliche Tools für die Analyse im Browser:
    • Google Chrome Developer Tools
    • Google Chrome PageSpeed Plug-in

Vorgehen auf der Server-Seite:

Wir führen generell einen Lasttest durch, um serverseitige Geschwindigkeitsprobleme zu finden. Hierfür benutzen wir Apache JMeter, eine Open Source Alternative, die aus unserer Sicht vollkommen ausreicht. Für die Durchführung eines Last-Tests ist Erfahrung nötig. So ist bspw. vielfach zu sehen, dass vergessen wird, eine Thinking-Time (darf reduziert werden, um den Punkt zu ermitteln, an dem der Server kollabiert) zu setzen. Erst diese ermöglicht es dem System, zuvor allokierte Ressourcen freizugeben.

Während JMeter seine Arbeit verrichtet, können Thread-Dumps erzeugt werden. In der Produktiv-Umgebung – in der kein Profiler aus Performance-Gründen zur Verfügung steht – kann man mit den Thread-Dumps Performance-Probleme identifizieren. Bei Linux wird für die Erzeugung eines Thread-Dumps ein „kill -3“ an den Prozess geschickt. Unter Windows sollte man hierzu den Java Befehl „jstack > threaddump.log“ benutzen. In dem File threaddump.log findet sich der Thread-Dump. Dieser zeigt für jeden Thread den Stack-Trace an und die Methode, die bei der Erstellung des Thread-Dumps ausgeführt wurde.
Anhand des Methodennamens kann das Problem lokalisiert werden. In diesem Projekt sahen wir, dass es viele Datenbankaufrufe gab. Ich möchte die Beschreibung hier etwas kürzen, es ist aber notwendig, alle serverseitigen Systeme in die Betrachtung miteinzubeziehen. So betrachteten wir natürlich auch den Tomcat und passten beispielsweise  die Memory-Einstellungen an. In unserem Fall hatten wir eine MySQL Datenbank. Bei dieser stimmten wir hauptsächlich die Parameter max_connections und innodb_buffer_pool_size ab. An diesem Punkt möchte ich anmerken, dass man oft sieht, dass der DB-Connection-Pool erheblich groß (bspw. 800) gewählt wird - hier ist ein Wert größer als 200 fraglich.

Liferay Einstellungen

Liferay ist über die Jahre um eine Vielzahl an Funktionen erweitert worden. Der Nachteil hierbei ist, dass viele dieser nicht benötigt werden und somit abgeschaltet werden können, was die Geschwingikeit einer Liferay-Installation verbessert.
Bei den Filtern gilt es folgende zu überprüfen:

com.liferay.portal.servlet.filters.gzip.GZipFilter=true
com.liferay.portal.servlet.filters.strip.StripFilter=false
com.liferay.portal.servlet.filters.sso.cas.CASFilter=false
com.liferay.portal.servlet.filters.sso.ntlm.NtlmFilter=false
com.liferay.portal.servlet.filters.sso.ntlm.NtlmPostFilter=false
com.liferay.portal.servlet.filters.sso.opensso.OpenSSOFilter=false
com.liferay.portal.servlet.filters.validhtml.ValidHtmlFilter=false
com.liferay.portal.servlet.filters.audit.AuditFilter=false
com.liferay.portal.servlet.filters.virtualhost.VirtualHostFilter=false
com.liferay.portal.sharepoint.SharepointFilter=false

Wir stellten nach wie vor eine schlechte Performance fest, selbst nachdem wir auch alle Datenbank-Caches (Hibernate und im Connection-Pool auf Tomcat-Seite) überprüft hatten. Wir installierten schließlich doch noch einen Profiler und schalteten bei der Datenbank das SQL-Log ein, um die Thematik exakter analysieren zu können. Wir fanden sehr viele Abfragen, die die Tabelle AssetEntry betrafen.

Bei genauerer Betrachtung stellten wir fest, dass sich die AssetEntry Queries nicht cachen ließen, da diese den aktuellen Zeitpunkt der Anfrage in den Attributen publishDate und expiration an das SQL-Select-Statement übergaben. Wir fanden weitere Abfragen, die die Tabelle Role betrafen und mehrfach ausgeführt wurden, obwohl man diese hätte zusammenfassen können. Im Peak hatten wir bis zu 729 Queries / Sekunde bei nur 10 Concurrent Usern!

Asset Publisher Portlet und das Thema Performance

Jetzt hatten wir das Asset-Publisher-Portlet in Verdacht. Dieses wurde von unserem Kunden überaus oft und sehr generisch benutzt, um Produktdokumente verschiedenen Produktlinien, gewissen Benutzern und Sprachen zuzuordnen.

Mit folgenden Einstellungen haben wir nochmals überprüft, ob das Asset-Publisher-Portlet die wirkliche Ursache für die Performance-Probleme ist:

  • Dieses Property wurde gesetzt, um Update Statements zu unterbinden: asset.entry.increment.view.counter.enabled=false
  • Validierung, ob Asset Publisher die schlechte Performance verursacht:
    • Liferay sehr schnell aber ohne Assets in der Ergebnisliste
      • asset.categories.search.hierarchical=false
    • 30% - 40% schneller
      • asset.filter.search.limit=10

Somit war für uns bewiesen, dass das Asset-Publisher-Portlet das Performance-Problem erzeugt.

Fazit

Generische Implementierungen haben oft den Nachteil, dass sie nicht sehr performant sind. Gerade SQL-Quereis müssen aus Performancegründen optimiert werden. Eine Alternative bieten hier Suchmaschinen, wie Apache Lucene, Solr oder elasticsearch.
Für das Asset-Publisher-Portlet gibt es folgende Möglichkeiten, um die Performance zu verbessern:

Die vielen Datenbank-Abfragen des Asset Publisher Portlets bedingen – wie oben beschrieben – die schlechte Performance des Liferay-Portals in der Version 6.1. Folgende Links zeigen auf, dass diese Problematik öffentlich bekannt ist: [1] [2]
Der zweite Link beschreibt die Option, in Liferay 6.1 die Datenbank-Abfragen durch Lucene-Abfragen zu ersetzen. Suchmaschinen können beispielsweise sehr viel schneller komplexe Abfragen abarbeiten, wie das mit einer SQL Datenbank möglich ist. Diese Architektur wurde auch in Liferay 6.2 umgesetzt. Ab 6.2 wird ein Lucene Index anstatt DB-Queries für das Asset Publisher Portlet verwendet [3].

„The Asset Publisher has received numerous improvements. Its performance has been improved significantly, as now it uses the search index (rather than database queries) to return entries. Users can subscribe to any list of content, and its UI has been simplified.”

Demzufolge ist eine Migration auf eine Liferay Version >= 6.2 in Erwägung zu ziehen und als einfacher anzusehen, als den Lucene Index in der Version 6.1 einzubauen.

Kategorien: LiferayPortale

Zurück