Project OpenMassMailer started

omm_logo_42x42_blog.png

This week I finally managed to start a new open source software project: OpenMassMailer. I saw the need for a simple yet flexible mass mailing solution after realizing that none of the existing open source software in this category could deliver exactly what we needed at the company.

OMM is not planned to become the one-size-fits-all solution for mass mailing. This is exactly what I found to be the problem of the existing solutions. OMM will be targeted at large companies that need a solution which fits perfectly into their workflow. An example? OMM will not feature an HTML editor. Why? Because if you do serious mass mailing at a large scale, you won’t create your newsletters with a sketchy editor in your browser - you have a web design department where the HTML for your newsletter will be produced in high quality using high quality tools.

In essence, with OMM, I want to follow this principle:

Il semble que la perfection soit atteinte non quand il n’y a plus rien à ajouter, mais quand il n’y a plus rien à retrancher.

(Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.)

The homepage of OMM is located at http://openmassmailer.org/.

My plan is to get other developers on board as early as possible. On ARSC, my former project, I worked mainly alone, and this time I would like to create a result of real teamwork.

If you would like to participate, the best place to go is the OMM Google Group at http://groups.google.com/group/openmassmailer/.

Everything developers need to know to get started will soon be available on the Trac wiki of OMM.

My-Hammer, das Fernsehen und die Serverlast: Teil 2.1

Dies ist Teil 2.1 der Artikelserie zum Thema Webseiten-Skalierung. Die anderen Teile:

Teil 1: Allgemeine Überlegungen
Teil 2: Datenbankoptimierung
Teil 2.1: Praxistipps Datenbank
Teil 3: Caching
Teil 4: Zukünftige Optimierungen (folgt)

Eine praxisnahe Zusammenstellung der Massnahmen, die sich bei My-Hammer.de bewährt haben:

InnoDB vs MyISAM

Ich schrieb bereits, dass man InnoDB nicht nur dann in Erwägung ziehen sollte, wenn man Transaktionssicherheit benötigt. Eine Tabelle von MyISAM auf InnoDB umzustellen kann unter Umständen Geschwindigkeitsvorteile bringen, nämlich dann, wenn das zweite wichtige Feature von InnoDB neben der Transaktionssicherheit, das Row Level Locking, effektiv zum Zug kommen kann. Um herauszufinden, ob dies der Fall ist, kann man wie folgt vorgehen:

Mitloggen aller Queries

Wenn man für einen bestimmten Zeitraum (bei einer gut besuchten Seite reichen wenige Minuten) einmal alle Abfragen, die an die Datenbank gestellt werden, mitschreibt, kann man aus diesem Log eine Menge interessanter Informationen ziehen. Um festzustellen, ob eine Tabelle vom Row Level Locking profitieren könnte, muss man die lesenden (SELECT) und schreibenden (INSERT, UPDATE, DELETE etc.) Abfragen gegenüberstellen.
Wird aus einer Tabelle sehr häufig gelesen, die Daten in der Tabelle aber nur sehr selten verändert, dann macht das Table Level Locking von MyISAM in der Regel keine Probleme: Zwar wird bei einem UPDATE, INSERT oder DELETE die gesamte Tabelle für nachfolgende Lesezugriffe gesperrt (d.h. diese müssen warten), bis der Schreibprozess abgeschlossen ist. Aber da dies nur selten geschieht, kommt es auch selten vor, dass ein Leseprozess warten muss, so dass daraus keine spürbare Verzögerung im Gesamtsystem resultiert.

Gleiches gilt im umgekehrten Fall: Wird in eine Tabelle praktisch nur geschrieben, aber selten daraus gelesen (wie es z.B. bei Logtabellen häufig der Fall ist), dann kollidieren auch hier die “Interessen” nur so selten, dass nicht mit Performanceeinbußen zu rechnen ist.

Slow Log

Interessant sind also jene Tabellen, bei denen Schreib- und Lesezugriffe in einem ausgeglicheneren Verhältnis stehen. In welcher Relation die beiden Zugriffsarten dabei mindestens stehen müssen, damit es sich “lohnt” InnoDB einzusetzen, ist schwer zu sagen. Ein Blick ins Slow-Log von MySQL hilft hier weiter: Wenn man immer wieder bei denselben Tabellen auf langsame Queries stösst, die nicht wegen des Queries selbst langsam waren, sondern weil sie auf ein Lock warten mussten, hat man auf jeden Fall aussichtsreiche Kandidaten.

SHOW PROCESSLIST

Eine weitere Methode ist, sich einmal für einige Minuten immer wieder die Liste der laufenden Prozesse in MySQL auflisten zu lassen (SHOW PROCESSLIST). Wenn man dort immer wieder dieselben Queries sieht, deren Status Locked ist, dann weiss man wo das Problem liegt. Diese Methode mag zwar auf den ersten Blick wie ein Glücksspiel wirken, aber gerade weil man immer nur die Prozesse sieht, die zufällig gerade laufen wenn man den Befehl absetzt, fallen die problematischen Prozesse erst recht auf, die immer wiederkehren und oft vielleicht sogar während zwei oder mehr SHOW Aufrufen immer noch laufen. Meiner Meinung nach die schnellste Methode, Flaschenhälse zu finden.

Mehr zum Thema Locking gibt es im Kapitel ‘Internal Locking Methods’ des MySQL Handbuchs.

Nehmen wir also an, man hat einige Tabellen identifiziert, bei denen Queries öfter als gesund ist auf einen Lock warten müssen. Dies könnte beispielsweise eine Sessiontabelle sein (falls man z.B. PHP nutzt und die Sessionfunktionen so angepasst hat, dass diese eine MySQL Datenbank als Storage nutzen, ein ziemlich klassisches Szenario). Diese Tabelle wird bei jedem Seitenaufruf zu Beginn einmal gelesen, um die Session des aufrufenden Benutzers zu laden, und am Ende des Skripts wird der Sessioninhalt dieses Benutzers wieder geschrieben. Also ein sehr ausgewogenes Verhältnis zwischen lesenden und schreibenden Zugriffen - jeder Seitenaufruf, der gerade an dem Punkt angelangt ist, an dem die Session geschrieben wird, würde also die Tabelle sperren für sämtliche anderen Seitenaufrufe, die in diesem Moment aus der Sessiontabelle lesen möchten - das Performanceproblem ist ab einer bestimmten Anzahl von gleichzeitigen Benutzern vorprogrammiert.

Klassischerweise geht man nun so vor, dass man die Tabelle in InnoDB umwandelt und wieder einige Zeit das Slow Log oder die Prozessliste beobachtet - sinkt die Lock_Time der Abfragen deutlich, hat man einen Flaschenhals erfolgreich eliminiert.

Nun, es wäre freilich zu schön, wenn es nicht doch den ein oder anderen Haken bei der Sache gibt; zum Glück lassen sich die meisten aber zumindest einigermassen elegant umschiffen.
Eine Einschränkung von InnoDB ist beispielsweise, dass der FULLTEXT Index nicht unterstützt wird. Dies war bei My-Hammer ein Problem, weil wir eine Tabelle, die ziemlich eindeutiger Kandidat für eine Umstellung von MyISAM auf InnoDB war, in einem Teil unserer Applikation auch durchsuchen mussten, und zwar eben gerade einige TEXT-Felder, was ohne FULLTEXT Index nicht wirklich Spass macht.
Die Lösung war, die Tabelle umzuwandeln und damit in der Tabelle selbst auf die FULLTEXT Indizes zu verzichten, per cronjob aber eine weitere Tabelle regelmässig mit den Daten der Ursprungstabelle zu füllen. Geschrieben wurde in diese Tabelle nur durch besagten Crobjobs, ansonsten fanden ausschliesslich Lesezugriffe statt, womit MyISAM wieder die perfekte Wahl war - und wir hatten unsere FULLTEXTs wieder. Schöner Nebeneffekt: durchsucht werden müssen eh nur eine Untermenge aller Zeilen der Ursprungstabelle, und es müssen auch nicht alle der (recht zahlreichen) Spalten in die Suchtabelle übertragen werden.
Dadurch konnten wir nicht nur das Lockingproblem der ursprünglichen Tabelle lösen, sondern aufgrund der schlankeren Datenbasis in der Suchtabelle die Suche deutlich beschleunigen.
Wichtig ist jedoch: diese Lösung ist nur möglich, weil wir in diesem Fall darauf verzichten können, auf absoluten Livedaten zu suchen.

My-Hammer, das Fernsehen und die Serverlast: Teil 1

Dies ist Teil 1 der Artikelserie zum Thema Webseiten-Skalierung. Die anderen Teile:

Teil 1: Allgemeine Überlegungen
Teil 2: Datenbankoptimierung
Teil 2.1: Praxistipps Datenbank
Teil 3: Caching
Teil 4: Zukünftige Optimierungen (folgt)

Vergangenen Donnerstag zeigte das ProSieben Magazin Galileo einen ca. 10-minütigen Beitrag über My-Hammer (kurze Infos zur Sendung hier). Vom Ansatz her ging es um “Branchenbuch vs. My-Hammer”, aber für die Betrachtung hier ist das gar nicht so sehr von Interesse - es ist noch nichtmal von Interesse, ob so ein Beitrag positiv oder negativ für uns ist (in dem Fall war’s wie fast immer positiv) - sobald das Magazin, in dem über uns berichtet wird, genug Reichweite hat, schießen die Zugriffe in die Höhe. Die wichtigste Erkenntnis, die wir immer wieder machen: zumindest bei den Privaten scheinen die Zuschauer sprichwörtlich mit dem Laptop auf den Knien vorm Fernseher zu sitzen. Die Zugriffe kommen extrem schnell und gebündelt (beim Galileo-Beitrag war aber interessant, dass die Zugriffe wieder auf einen Schlag kamen, aber erst in dem Moment, in dem der Beitrag vorbei war).

Genau dieses plötzliche Auftreten so vieler Zugriffe ist natürlich die Herausforderung - dieselbe Anzahl User auf nur 15 Minuten verteilt wären kein Problem, aber TV sorgt dafür, dass das meiste innerhalb der ersten 5 Minuten passiert. Und es ist wirtschaftlich natürlich ziemlich unvernünftig, die für diese 5 Minuten benötigte Rechenpower anzuschaffen, nur damit sie die anderen 525.595 Minuten im Jahr vor sich hindümpelt.

Trotzdem kann man eine Webseite auch auf solche Extremsituationen vorbereiten - My-Hammer hat am Donnerstag perfekt standgehalten, lediglich eine leichte Verzögerung in den Ladezeiten war während der kritischen Phase spürbar.

Um kurz die Dimensionen klarzumachen, erstmal eine Grafik, welche den ein- und ausgehenden IP Traffic für unser Netzwerk anzeigt. Man sieht sehr deutlich den Sprung auf das gut 2,5-fache des normalen Werts. Der Faktor selbst klingt vielleicht erstmal nicht so dramatisch, aber wie erwähnt geht es nicht um die Masse an sich, sondern das extrem gebündelte Auftreten dieser Masse an Zugriffen:

IP-Traffic My-Hammer

Ich behaupte mal, man erkennt recht gut, wann die Sendung lief…

Also, wie kann man die Serversysteme auf so etwas vorbereiten? Klar: mehr Server kaufen. Das ist durchaus ein Aspekt, aber nicht das Allheilmittel. Vor allen Dingen kann das sehr ineffektiv und unwirtschaftlich sein. Angenommen, man hat Server A mit einer gewissen Leistungsfähigkeit. Nun kann man sich Server B mit doppelt so schnellem Prozessor, doppeltem Arbeitsspeicher und doppelt so schnellen Festplatten kaufen. Dann hat man schon Unmengen von Geld ausgegeben, und hat gerade mal eine Steigerung der Leistungsfähigkeit von 100% (mal davon abgesehen, dass die Rechnung “doppelt so schnelle Hardware, doppelt so viel Leistung” in der Praxis auch nicht wirklich hinhaut). Dagegen kann ein einziger geschickt gesetzter Index in der Datenbank manchmal 1000% bessere Performance bringen, ohne dass man etwas an der Hardware tut.

Wenn man den Anschaffungspreis neuer Hardware mal auf den Stundenlohn eines Entwicklers umrechnet, wird man schnell zu dem Schluss kommen, dass es sich auch finanziell durchaus rechnen kann, diesen einige Tage lang auf die Datenbank anzusetzen um zu schauen, ob nicht doch irgendwo ein wichtiger Index vergessen wurde oder einige Tabellenstrukturen besser ganz anders aufgebaut sein sollten.

Das sind nur ein paar grundsätzliche Überlegungen. Spürbaren Erfolg wird man nur haben, wenn man ein ganzes Bündel an Massnahmen ergreift und vor allem immer das Gesamtsystem vom Code über die Datenbank bis hin zu den Servern und dem Netzwerk im Überblick hat. Die vielleicht wichtigste Faustregel, wenn man über Performanceoptimierung von Webseiten spricht, scheint mir daher zu sein: Coder und Admins an einen Tisch! Es hilft nichts, wenn die Entwickler meinen, die Geschwindigkeit des Systems sei doch schliesslich Sache des Admins. Umgekehrt ist es extrem hilfreich, wenn die Programmierer auch einen gewissen Sysadmin-Background haben, und die Admins umgekehrt auch Programmiererfahrung haben; was bei uns glücklicherweise sogar sehr ausgeprägt der Fall ist.

Die weiteren Teile befassen sich mit den konkreten Massnahmen, die man ergreifen kann um sich auf einen TV Beitrag vorzubereiten.

Using apt on Etch connecting to an apt-proxy on Sarge causes trouble with .diff files

openlogo-nd-50.pngSay you have an installation of apt-proxy running on a Debian Sarge machine to serve files for apt on your other machines, then you will receive errors like this when issuing an apt-get update on an Etch machine: Error reading from server. Remote end closed connection.The reason is that Etch tries to download a file called Packages.diff which Sarge’s apt-proxy doesn’t know how to serve.

apt-proxy therefore log notes the following:

2007/02/09 10:10 CET [Channel,129,213.203.200.122] [debug] Request: GET /debian/dists/etch/main/binary-amd64/Packages.diff/Index
2007/02/09 10:10 CET [Channel,129,213.203.200.122] [debug] abort - unknown extension

Adding the following line to /etc/apt/apt.conf on your Etch machines will tell them not to download those files:

Acquire::PDiffs “false”;

ARSC Really Simple Chat

As my server crashed last week, I decided to not set up a homepage for my Open Source webchat project ARSC again.
It simply isn’t worth the hassle, because I didn’t do any work on ARSC for over 1 year now.

The SourceForge project page of ARSC is of course still active, and I don’t see any sense in deactivating it, because the latest stable release still works very well, supporting PHP4 and PHP5, MySQL 4 and 5, register_globals = Off and PHP’s safe_mode.

Next Page »
Photograph of Manuel Kiessling
My XING profile
My LinkedIn profile