Managing Tech

Managing Technology, from the trenches

Infos

Im privaten Blog von Jan Miczaika geht es um die Arbeit mit Technologien, in Teams, und das insbesondere im Startup-Umfeld. Kontakt?
    jan -at- hitflip.de oder bei XING

Das ist ja mal ein abstrakter Titel! Aber im Artikel versteckt sich einer der besten Skalierungstipps, die ich derzeit im Angebot habe.

Normalerweise sind alle Webapplikationen durch Benutzer-Events getrieben. Der Surfer klickt irgendwo, stößt ein Skript an, das macht irgendwas und er kriegt ein Ergebnis. Spannend wird es immer dann, wenn dieses “irgendwas machen” länger dauert, als man dem Surfer zumuten möchte. Dann geht es los mit Cronjobs und Spooler-Tabellen. Es geht aber auch schlauer.

Ein Beispiel aus unserem Alltag: wenn sich bei Hitmeister der Preis eines Artikels ändert, gucken wir ob jemand per E-Mail informiert werden möchte (Preisalarm). Jetzt ändert sich auch der Preis eines Artikels, wenn jemand etwas in den Warenkorb legt. Soll derjenige, der sogar noch im Kaufprozess ist, warten bis alle Mails verschickt wurden? Sicher nicht.

Der klassische Ansatz wäre hier einen Spooler einzubauen, der dann durch einen Cron abgearbeitet wird. Das ist auch eine zeitlang sinnvoll. Nur gibt es bei großen Projekten irgendwann dutzende Crons mit entsprechenden Tabellen. Man muss die Crons warten, den Tabellenstand überprüfen, den Verlauf monitoren usw. Nicht schön.

Die Lösung? Events und ein Observer Pattern. Wir haben eine kleine message queue programmiert. Da drin gibt es eine Queue, /Events (Füchse erkennen direkt die baumartige Struktur). In dieser Queue stehen dann Meldungen mit einem header und einem body, wie z.B.

header | body
PriceChange | id_item = 12345
ContentUpdate | id_item = 56789
NewOrder | id_order = 1234

Der Body ist ein serialisiertes Array (hier vereinfacht dargestellt). Jetzt gibt es nur eine Komponente, bei uns einfallsreicherweise Observer genannt, die diese Queue abarbeitet. Jeder header entspricht dabei einer Klasse. Wenn ein header kommt, wird der Code in der klasse ausgeführt. Die Parameter im body reichen dabei aus, um alles auszuführen. Hinterher wird die message gelöscht.

So ein Observer ist eine prima Sache. Jeder, der etwas asynchron verarbeiten möchte, kann dem Observer mitteilen bei welchen Events etwas aufgerufen werden soll. Artikel in Exporten modifizieren, wenn der Artikel sich ändert? Kein Problem. Langsame externe URLs aufrufen, wenn es eine neue Bestellung gibt? Auch easy.

Und wenn man den Observer saubert programmiert (ACID usw.) dann kann der auf beliebig vielen Rechner laufen. Und zack können wir eine Weile länger horizontal skalieren!

Wir haben unsere Message Queue selbst programmiert. Wer das ganze in Groß angehen möchte, sollte sich AMQP, RabbitMQ und ActiveMQ anschauen (alle in Java, aus dem Bankenumfeld). Die bieten dann nette Features wie Priorisierung, Echtzeit-Messages usw. Man kann auch Amazon SQS verwenden, wobei ich eine ausgelagerte Queue wegen der hohen Latenz für ziemlich sinnlos halte.

5 Responses to “Skalierung mit dem Observer Pattern und Events in PHP”

  1. Wir setzen bei uns seit kurzem ActiveMQ ein. der Mailversand läuft über eine Queue, außerdem implementieren wir täglich wiederkehrende Prozesse inzwischen damit. Aus Performance Gründen berechnen wir einige Werte für die Ausgabe auf User-Basis vor, die werden dann alle auf einmal in die Queue geworfen und dann nach und nach mit geringer Priorität abgearbeitet. Für uns ist dabei ebenfalls ein Vorteil, dass die Queue persistiert wird und damit auch einen Server-Neustart überlebt.

    Sebastian

  2. Hi Sebastian, klingt spannend. ActiveMQ würde ich gerne irgendwann auch mal ausprobieren, evtl. statt unserem Eigenbau…

    Vom Prozess her ist der Ansatz bei uns etwas anders. Wir stecken fast nur IDs in die Queue und lassen dann den Observer die ganze Arbeit machen, statt den Cron. Das ist m.E. besser skalierbar, aber letztendlich wohl auch nur Geschmackssache…

    Jan

  3. ActiveMQ unterstütz meines Wissen auf non-Java/C++ Ebene nur das Stomp Protokoll. Das erlaubt so gut wie keine weiteren Steuermechanismen/Routings zu nutzen.

    Ausserdem ist es halt typisch JEE - für den einen super, für den agilen Rails/Perl/PHP-Entwickler jedoch einfach nur Horror.

    Roland Moriz

  4. Hallo Roland,

    ich schaue mir derzeit RabbitMQ, angesprochen über HTTP an. HTTP ist leider etwas langsam für ein Messaging Protokoll. Aber im Vergleich zur Latenz zum Amazon SQS ist es ok.

    Jan

  5. […] rieche hier einen Trend. Ich hatte vor einiger Zeit über das Thema Skalierung mit dem Observer Pattern geschrieben. Jetzt entdecke ich auf der (guten aber doch recht generellen) Liste “Startup […]

    Managing Tech » Blog Archive » Skalierbare Startups bauen lose gekoppelte Systeme

Leave a Reply