ActiveMQ, skalierbare Infrastruktur durch Messaging
ActiveMQ ist ein Open Source Message Broker, den ich für Messagequeues benutze. Vielleicht verliere ich dazu mal ein paar erklärendere Worte: Wenn eine Softwarekomponente mit einer anderen asynchron Nachrichten austauschen will, müssen diese Nachrichten irgendwo gespeichert und irgendwo abrufbar sein.
Ich spiele gerade im Bereich Medientranskodierung damit. Ein User lädt irgendein Medium hoch, gibt ein paar deskriptive Daten wie den Titel und eine Beschreibung ein und dann soll das Medium in verschiedene Medienformate für Flash, iPod usw. transkodiert werden. In Echtzeit macht der Server das nicht, also werden Jobs generiert, die irgendwann, der Reihe nach, abgearbeitet werden. Früher schrieb ich diese mit einem Zeitstempel versehen in die Datenbank und arbeitete sie chronologisch getriggert über Quartz ab. Seit Java 1.5 kann man das Spiel mit einer LinkedBlockingQueue ohne Quartz schöner machen - ist ein Job da, blockiert die Queue und bearbeitet den Job, ist er abgearbeitet, kümmert sie sich um den nächsten (bzw. wartet auf ihn, sollte die Queue leer sein). Funktionierte auch gut. Aber was, wenn ein weiterer Rechner beim Transkodieren behilflich sein will?
Da ist ein Message Broker wirklich nett. Ich schreibe eine Nachricht mit beliebigem Inhalt (Plaintext, serialisierte Objekte in JSON oder XML, einfach alles) in eine beliebig benannte Queue, und bringe meiner Webapplikation bei, diese abzufragen und zu verarbeiten. Wenn mehrere Rechner dabei helfen wollen ist das prima, einfach eine Nachricht nehmen, auswerten, transkodieren, und … reporten. Ja, Reporting ist wichtig, und da bietet sich ja gleich eine Nachricht für eine andere Queue an. Auf die dann wieder reagiert werden kann, z.B. durch Verlinken des neuen Medienabkömmlings.
ActiveMQ muss übrigens nicht zwangsläufig mit Java über JMS angesprochen werden, es gibt eine Vielzahl von Schnittstellen raus aus der Javawelt - REST, Stomp und XMPP (Jabber) sind eine Auswahl spannender Zugriffsprotokolle. Alternativen gibt es aber auch, z.B. Amazons Simple Queueing Service (SQS), der pro Nachricht (wenig) Geld kostet. Oder RabbitMQ, auf Erlang-Basis. Lief aber leider nicht auf meinem Ubuntu 6.06 Server, für den es das benötigte Paket erlang-nox nicht gibt.
Aprospos Ubuntu 6.06 Server: Ich habe ActiveMQ 5 runtergeladen, nach /opt/activemq entpackt und mir ein Initscript geschrieben, da ich keines fand. Bitteschön hier. ActiveMQ als Binärpaket hat mir mehr Spaß bereitet, das Bauen der Quellen mit Maven2 (und integrierte Testen) brach auf einem Quad-Xeon nach 58 Minuten(!) fehlerhaft ab. Einfach in /etc/init.d/activemq kopieren, mit “chmod +x /etc/init.d/activemq” ausführbar machen und mit “/etc/init.d/activemq [start|stop|status]” nutzen. Oder mit “update-rc.d activemq defaults” gleich mit den Startupscripts bekanntmachen.
Out-of-the-Box kommt ein Jetty als Applikationsserver mit, der Demos (http://[DEIN_HOST]:8161/demo) und Administrationsinterface (http://[DEIN_HOST]:8161/admin) die ersten Experimente erleichtert. Die ganze Standardkonfiguration von ActiveMQ ist offen wie ein Scheunentor, für den Produktiveinsatz sollte man sich mit den Sicherheitsmöglichkeiten (zwei gibts) auseinandersetzen oder den Server zumindest durch eine Firewall abschirmen.
In Grails 1.0.2 konnte ich mit dem JMS Plugin 0.3 sehr schnell loslegen. Mit ein bischen Meta-Object Programming Magie durch das Pluginsystem stehen jedem Controller und jedem Service Methoden zum Versand von Nachrichten bereit. Empfangen werden Sie ueber Services, Namenskonventionen erleichtern auch hier die Arbeit: Ein Service JobQueueService beobachtet die Queue namens “job” und die Closure onMethod verarbeitet einkommende Nachrichten der Reihe nach. Vorrausgesetzt, der Service lauscht auch. Nach dem Keep-It-Simple-Stupid-Prinzip habe ich meinem Service ein Ohr gegönnt (listenerCount=1), nehme es ihm sobald eine Nachricht eintrifft weg (listenerCount=0) und gebe es ihm anschließend sofort wieder. Ob das eine besonders gute Idee ist, weiss ich noch nicht, aber sie ist schön einfach.
In diesem Sinne, frohe Ostern
