1 Einleitung
In diesem Tutorial geht es darum, wie man Apache und einen Glassfish Server miteinander verbinden kann, so dass der Apache “vor” dem Glassfish Server sitzt und alle Anfragen an den Glassfish weiterleitet. Dies funktioniert mit dem Apache-Modul “mod_jk”.
2 Voraussetzungen
Für dieses Tutorial habe ich folgende Umgebung und Versionen verwendet:
- Ubuntu 8.04.4 LTS
- Apache 2.2.8
- Glassfish 3.1.1
- mod_jk 1.2.32
Aber das Tutorial dürfte sich leicht auf eine andere Umgebung übertragen lassen…
3 “mod_jk” kompilieren
Leider gab es für meine Umgebung kein vorkompiliertes “mod_jk”, das bedeutet also: selbst kompilieren! Auf http://tomcat.apache.org/download-connectors.cgi gibt es die Source Releases, bei mir war die aktuellste Version 1.2.32. Dann den Download auspacken, im Archiv gibt es eine BUILD.txt, die den Kompiliervorgang beschreibt. Auszug (kann man so noch nicht verwenden):
$> cd native
$> ./configure --with-apxs=/usr/sbin/apxs (or where ever the apxs/apxs2 is)
$> make
$> su -c 'make install'
Ich habe über apt (oder synaptic) das Paket “build-essential” installiert, mit dem fast alle Voraussetzugen für diesen Kompilier-Vorgang erfüllt sind. Lediglich apxs (bzw. apxs2) fehlt, was man offensichtlich für das “configure” benötigt, wie oben zu sehen. Hier habe ich in synaptic nach apxs gesucht und so zwei Apache-Pakete gefunden. Für eines von beiden muss man sich entscheiden, ich habe das “threaded”-Paket gewählt. Ob es mit dem anderen Paket auch funktioniert, habe ich nicht getestet (für Feedback bin ich dankbar!). Danach liegt apxs bei mir unter folgendem Pfad (ein “find” sollte die Datei ausfindig machen):
/usr/bin/apxs2
Damit können wir also den Kompilier-Vorgang folgendermaßen durchführen:
$> cd native
$> ./configure --with-apxs=/usr/bin/apxs2
$> make
$> su -c 'make install'
Das Kompilieren sollte nun ohne Fehler durchlaufen. Falls configure oder make doch noch etwas anmeckert, dann sind es oft Header-Dateien, die in den entsprechenden “dev”-Paketen enthalten sind, die man leicht mit synaptic finden und nachinstallieren kann.
4 “mod_jk” konfigurieren
Wenn “mod_jk” fertig kompiliert und installiert ist, muss es noch über zwei Konfigurations-Dateien konfiguriert werden.
Die erste ist die workers.properties. Also eine Datei workers.properties anlegen, egal wo, aber am besten unter /etc/apache2/ mit folgendem Inhalt:
worker.list=worker1
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009
Wir müssen diese Datei später noch erweitern, aber für den Anfang reicht es so.
Dann muss die Apache-Konfigurations-Datei /etc/apache2/httpd.conf angepasst werden (war bei mir anfangs leer). Einige Eigenschaften verweisen auf Pfade, die natürlich stimmen müssen, d. h. die mod_jk.so-Datei vorher mit “find” ausfindig machen und den richtigen Pfad hier einsetzen. Das gleiche gilt für die log-Dateien und ganz wichtig: die zuvor angelegte workers.properties:
LoadModule jk_module /usr/lib/apache2/modules/mod_jk.so
JkWorkersFile /etc/apache2/workers.properties
JkLogFile /etc/apache2/mod_jk.log
JkLogLevel debug
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
JkRequestLogFormat "%w %V %T"
JkMount /yourWebApp/* worker1
JkMountCopy All
Die vorletzte Zeile (JkMount) gibt an, dass alle Anfragen von /yourWebApp/* zu dem Alias “worker1″ aus der workers.properties-Konfigurations-Datei weitergeleitet werden. Von da geht es dann zu dem dort konfigurierten Host und Port (bei mir localhost:8009) weiter.
ACHTUNG: Wenn man für JkMount /yourWebApp/* konfiguriert, dann darf in der Anfrage das abschließende Slash (“/”) nicht fehlen. Darauf bei eventuellen Weiterleitungen achten! Folgende Anfrage würde funktionieren:
http://yourdomain.com/yourWebApp/
Folgende Anfrage würde NICHT funktionieren:
http://yourdomain.com/yourWebApp
Die letzte Zeile in workers.properties (JkMountCopy All) vererbt die JkMount-Konfiguration auf alle eventuellen VirtualHosts.
Mit JkLogLevel debug fallen sehr viel log-Daten an, ich fahre aktuell ganz gut mit JkLogLevel info.
5 Glassfish konfigurieren
Die Konfiguration des Glassfish erweist sich als denkbar einfach. Über zwei Kommandos muss der jk-connector des Glassfish aktiviert werden:
asadmin create-http-listener --listenerport 8009 --listeneraddress 0.0.0.0 --defaultvs server jk-connector
asadmin set configs.config.server-config.network-config.network-listeners.network-listener.jk-connector.jk-enabled=true
6 Glassfish-Bug beheben
An dieser Stelle kann nach einem Neustart von Apache und Glassfish ein erster Verbindungs-Test vorgenommen werden, d. h. einfach mit einem Browser folgende URL besuchen:
http://yourdomain.com/yourWebApp/
Ohne die soeben vorgenommenen Schritte hätten wir mit Sicherheit eine 404-Seite erhalten, jetzt würden wir aber die Startseite der WebApp erwarten. Dummerweise erschien bei mir nur eine weiße Seite. Immerhin kein 404, was bedeutet, dass Konfiguration zumindest ansatzweise gefruchtet hat. Nach einiger Log-File und Internet-Recherche bin ich auf folgenden Thread gestoßen, der einen Glassfish-Bug behandelt: http://forums.java.net/node/821526.
Der Fix besteht darin, eine Datei im Glassfish auszutauschen, und zwar
grizzly-utils.jar
Diese Datei kann man in dem Thread downloaden. Danach Glassfish neu starten und die Startseite der WebApp sollte erscheinen.
7 Verbindungsprobleme
Einfache WebApps sollten mit dieser Einstellung zumindest grundlegend laufen. Sobald aber ein wenig mehr Last anliegt, dürften bei dieser Konfiguration die ersten Verbindungsprobleme auftreten. Mit Firefox und zugehörigem Plugin “Firebug” kann man sehen, dass manchmal auf eine bestimmte Resource (Bilder, css oder JavaScript-Dateien, manchmal die Seite selbst) sehr lange gewartet wird. Irgendwann (nach ein paar Minuten) wird die Resource aber dann doch noch ausgeliefert. So lange wird ein User natürlich nicht warten.
Anfangs spekulierte ich auf einen Bug in mod_jk, nach einiger Recherche bin ich dann allerdings auf diese Website gestoßen: http://community.jboss.org/wiki/OptimalModjk12Configuration. Dort ist erklärt, dass die Standard-Konfiguration von Apache und mod_jk ungeeignet für den produktiven Betrieb sind. Hauptsächlich geht es um ungünstige Defaults von Timeouts, die entweder viel zu hoch angesetzt sind oder überhaupt nicht greifen.
Die Erklärung auf dieser Seite ist allerdings nicht für Glassfish, sondern für Tomcat. Man kann aber trotzdem einen Großteil der Vorschläge dort umsetzen. In Glassfish selbst ist es ohnehin nur eine Einstellung, und zwar die max-thread-pool-size, die man leicht mit folgendem Kommando auf 200 setzen kann (Default ist 5):
asadmin set configs.config.server-config.thread-pools.thread-pool.http-thread-pool.max-thread-pool-size=200
Die restlichen Konfigurationen für workers.properties und Apache bitte dem Link entnehmen.