Tomcat, Java, Clustering, Multicast und … IPv6

23. September 2010


 

Wenn es nicht so viel zu tun gäbe, hätte ich sicher schon eher mal wieder etwas gebloggt, etwa aus der wunderbaren Welt von Grails, welches neben byzantinischen Stacktraces auch sehr interessante Fehlermeldungen bei zirkulären Abhängigkeiten zwischen Klassen generiert. Aber irgendwie kam immer was dazwischen.

Die letzten drei Tage habe ich aber nur an einem dummen Problem gesessen, so dass ich kein schlechtes Gewissen habe, eben mal eine Stunde mit dem Verfassen launischer Texte zu verbringen.

Was habe ich also drei Tage lang gemacht? Eigentlich wollte ich nur mal eben schnell bei mir lokal einen Dummy-Tomcat Cluster testweise zum Laufen bekommen, weil das „eben mal schnell kurz vor dem Launch auf live aufsetzen“ für einen ungesund hohen Adrenalinspiegel bei den Admins sorgt.

Also zwei Tomcats hingestellt, das build-system dazu überredet, beide zu deployen, die Dokumentation unter http://tomcat.apache.org/tomcat-5.5-doc/cluster-howto.html nachgeschlagen und angefangen, in der server.xml rumzubasteln.
Das geht ja einfach: einen einfügen, ggf. ports anpassen, und fertig zum Testen.

Nur schlägt schon der erste Versuch fehl; die Server klagen die logs voll mit solchen Dingen wie:

FEIN: Unable to send mcast message.
java.io.IOException: Invalid argument
        at java.net.PlainDatagramSocketImpl.send(Native Method)
        at java.net.DatagramSocket.send(DatagramSocket.java:625)
        at org.apache.catalina.cluster.mcast.McastServiceImpl.send(McastServiceImpl.java:316)
        at org.apache.catalina.cluster.mcast.McastServiceImpl$SenderThread.run(McastServiceImpl.java:401)

Na schön … das letzte mal, das ich am clustering verzweifelt bin, war mit einer JGroups installation, und der Grund war nicht JGroups, sondern dass in meiner Linux-installation für Multicast keine Route eingetragen war. Also:

route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0

Hilft es? Nein … also Tomcat sourcen geholt, nach einer Weile geschafft, diese zu übersetzen (das geht beim 5.5 nur mit java1.4, scheint mir, und das build-system reagiert launisch, wenn man das erst auf halbem Weg bemerkt …), und diverse Debugging-versionen erstellt.

Was daran geholfen hat, ist, dass Tomcat mit kaputtem Clustering immer eine Weile braucht, bis er das Handtuch wirft, und vorher will er auch nicht heruntergefahren werden. Die Zeit bis dahin kann ich ja mit Googlen herumbekommen … und mich nachher wundern, wieso ich noch nicht vorher auf folgendes gekommen bin …
Kurz gesagt: für den simplen Suchbegriff „java ipv6“ schlägt Tante Google folgendes vor:
http://ardvaark.net/how-to-make-java-ignore-ipv6
und siehe da: einfach eine Zeile

export CATALINA_OPTS="$CATALINA_OPTS -Djava.net.preferIPv4Stack=true"

in Startscript gehackt, und schon funktioniert alles.
Phew. Mein Dank ans Erdferkel. (En Anglais: Muchas Gracias, Ardvaark!)

Als Seiteffekt des Rumgestochere in den Tomcat-Sourcen kann ich zumindest mitteilen, wie sich die Multicast-Addresse ändern lässt, an die sich der Tomcat abboniert. Das magische Attribut am -element lautet nämlich mcastAddr (und nicht mcastAddress, wie ich zunächst in Analogie zu der dokumentierten mcastBindAddress vermutet hatte).

Eine für Testzwecke brauchbare server.xml sieht damit in etwa so aus:

[...]

   [...]
   
   
   [...]

[...]

Nun noch für ${tomcat.cluster.multicast.address} eine geeignete IPv4-Multicast-Addresse eintragen und fertig ist der Testcluster. (Für den Produktivbetrieb wird sicher noch ein wenig nachjustiert.)

Achso, und noch ein Bonbon: mit

netstat -ng

lassen sich alle Multicast Addressen anzeigen, auf die der aktuelle Rechner abbonniert ist. Das steht in der man-page, man muss sie nur lesen.

P.S.: ja, ich weiss, mit tomcat 6.0 oder 7.0 ist sicher alles viel besser (da heisst das fraglich Attribut „address“ statt „mcastAddr“) … aber irgendwie schätzen es manche Kunden, wenn Software eingesetzt ist, die so alt ist, dass alle wesentlichen Bugs schon bekannt sind …