[Postfixbuch-users] OT: Meinungsumfrage "Aushändigen von Logfiles"

Thomas Gelf thomas at gelf.net
Mo Jun 8 12:11:52 CEST 2009


Thomas Schwenski schrieb:
> Die Variante der flachen Tabellen ist die eine Möglichkeit.
> Ich vermute aber mal, dass Du meinst, dass wenn ich anstelle der
> redundanten Speicherung von E-Mail-Adresse und Domain dort nur einen
> Fremdschlüssel einer anderen Tabelle reinschreibe, die JOINs zwischen
> den Tabellen zu aufwändig wären?

Nein, meine Tabelle sieht in etwa so aus:

| id | from_address  | from_domain | to_address | to_domain | ...
|----|---------------|-------------|------------|-----------|-----
| 23 | mail at from.dom | from.dom    | tom at my.dom | my.dom    | ...

Die Suchanfragen haben fast immer eine E-Mail-Adresse, eine Domain oder
auch "peter%@domain.tld" sowie eventuelle zusätzliche Filter (z.B. nur
Spam in Quarantäne, nur Rejects) zum Inhalt. Zudem verhält es sich bei
mir so, dass ich einige wenige Domains mit vielen tausend Postfächern
sowie ziemlich viele Domains mit eher wenig Postfächern habe. Sich da
etwas zu Basteln, das mit JOINs arbeitet und in jeder zu erwartenden
Abfrage-Variante performant verhält ist ein ziemliches Unding.

Wie dann gesucht und gefiltert wird entscheidet die Applikation. Geht
es bloß um die Domain wird die entsprechende Spalte verwendet, ist die
Adresse exakt angegeben wird in eben dieser Spalte gesucht - wird eine
Domain und ein Teil des "lokalen" (User-)Teils angegeben, werden beide
Spalten (!) benutzt.

Mit einem besseren DBMS könnte man sich hier sicher einiges davon sparen
- den Query Optimizer von MySQL kannst du aber je nach Anwendung so
ziemlich vergessen. Und du musst dich SEHR intensiv damit auseinander-
setzen um zu verstehen, warum er sich einmal so und einmal anders
verhält. Man muss es ja aber auch nicht übertreiben, wenn du wie du
schreibst eher geringes Mailaufkommen hast, dann reicht es auch, der
DB einfach ausreichend RAM zur Verfügung zu stellen - brachiale Rechen-
gewalt hat dann definitiv das bessere Preis/Leistungs-Verhältnis ;-)

> Außerdem werde ich die in der Datenbank gespeicherten Logs auch nicht
> ewig aufheben sondern nur so lange wie eine live-Rückverfolgung
> überhaupt sinnvoll ist.

Machen wir hier auch, die "live"-Rückverfolgung ist nur für 14-30 Tage
verfügbar - sollte mehr benötigt werden kann ich das aber mit wenigen
Schaltern umstellen.

> Darüber hinaus logge ich zusätzlich weiterin in Dateien.

Idem. Ziel der Applikation ist es explizit NICHT, das Logging zu
ersetzen.

> Jetzt muss ich mal nachfragen:
> Du loggst also nicht original in die Datenbank sondern Deine
> Schnittstelle zwischen Syslog/Pipe und der Datenbank wertet die Logfiles
> erst aus?

Richtig.

> Sprich: nur 1 Datensatz je Mail?
> Oder willst Du nur eine ID bei allen Datnsätzen zu einer Mail haben.

IDs werden zwar vergeben, aber nirgends benutzt. 1 Datensatz pro
Empfänger einer Mail. Ein relationales Modell nutzt z.B. Amavis in
seiner DB. Und obwohl da die ganzen Rejects (die immerhin locker 90%
bis 95% ausmachen) noch gar nicht dabei sind, waren neben einigen
schnell durchführbaren Abfragen andere wiederum quälend langsam.
Außerdem dauerte es damals volle vier Tage, bis die erste von 5 Ab-
fragen zur "Garbage Collection" auf dem letzten Slave fertig war :o)

> Ich dachte schon an ein Logging der Original-Zeilen in der DB.

Diesen Gedanken hatte ich am Anfang auch mal, habe den dann aber ganz
schnell verworfen, weil:

- die DB dann RICHTIG schwitzen darf und ihre eigentlichen Stärken
  nicht zum Einsatz kommen
- du ein paar Problemchen bekommst: sende eine Mail an zwei Empfänger,
  einem davon als Blindkopie - und dann führe einen Grep auf's Amavis-
  Log nach ersterem durch. So etwas darf er NIE zu Gesicht bekommen
- die Zielgruppe 0815 Kunden bis maximal Exchange-Admins sind. Die
  sind meist bereits mit einem 5xy-Code restlos überfordert.

Damit du dir vorstellen kannst wie das Ganze aussieht, habe ich dir
unter http://devel.gelf.net/logparser/ ein paar Screenshots online
gestellt.

>> Und vor noch einem bösen Effekt möchte ich dich warnen: du kannst
>> dich nicht darauf verlassen, dass die Reihenfolge der Log-Einträge
>> mit der Reihenfolge der Operationen übereinstimmt. So kann schon
>> mal laut Log ein Mail in der Queue angekommen sein, bevor du den
>> entsprechenden "connect"-Eintrag erhältst (da mehrere Prozesse und
>> CPU-Cores...).
> 
> Dazu gibt es in dem Log-Pipe-Eintrag doch einen Timestamp, oder?
> Den wollte ich verwerten für die Zeitangabe in der Datenbank.

Timestamp -> klar. Bringt aber wenig, wenn alles in derselben Sekunde
passiert. Wenn du die vollständigen Zeilen reinschreibst kann dir das
natürlich egal sein - ich "baue" mir aus den Log-Zeilen von mehreren
Postfix und Amavis-Instanzen eine DB-Zeile pro Empfänger und Mail.
Naja, und da muss ich eben irgendwie "erkennen" was alles zu einem
Mail gehört. Ist dann halt ein wenig blöd, wenn etwas "queued as XY"
ist, ich aber noch keine passende "connect"-Zeile erhalten habe und
es somit nicht wirklich zuordnen kann. Ich muss mir die Zeile "merken",
und damit fängt das große Kopfzerbrechen dann auch schon an ;-)

Noch was bzgl Timestamp: ORDER BY ist auch so ein Kandidat, der sich
SEHR negativ auf die Performance auswirkt bzw so richtig tödlich sein
kann...

>> Wie ich das Ganze hier bei uns umgesetzt und aufgebaut habe (mit
>> besonderem Augenmerk auf die ganze Log-Geschichte) stelle ich
>> übrigens am 02.07. auf Peer's Mailserver-Konferenz in Berlin vor:
>>
>> http://www.heinlein-support.de/mk/mk09-der-oss-mailcluster-von-raiffeisen-online/
>>
>> Vielleicht hat ja der ein oder andere Lust und Zeit, sich das anzu-
>> hören - werde mich bemühen nicht allzu viel Unsinn zu erzählen ;-)
> 
> Ich hoffe davon gibt's einen Stream/Video-Download, denn die Teilnahme
> ist bei mir leider ausgeschlossen.

Da müsstest du Peer fragen, habe ehrlich gesagt keine Ahnung ob so etwas
geplant ist.

> Interessiert bin ich an dem Projekt auf jeden Fall, aber das merkt man
> ja sicherlich.

Merkt man ;-)

> Was mich aber vor allem interessieren würde, wie hast Du das Auslesen
> der Pipe gemanagt?
> Lässt Du die nur per Schleife auslesen, auswerten, INSERTen?
> Oder übergibst Du die Informationen an einen eigenen Thread, der sich um
> Auswertung und Datenbank-Eintrag kümmert um schnell wieder die Pipe
> auslesen zu können?
> Gerade die letzte Variante scheint mir bei eurem Mailaufkommen sinnvoll.

Thread -> leider nein. Zum Einsatz kam aus unterschiedlichen Gründen
PHP - obwohl es ganz und gar nicht hierzu geeignet ist. Macht einfach
keinen Spaß, wenn deine Probleme lediglich durch seit 3 Jahren bekannte
Memory-Leaks verursacht werden, die "nicht weiter schlimm" sind, weil
"nach dem Ende des HTTP-Requests ohnehin der gesamte Speicher wieder
freigegeben wird" :-( Oder Signal-Handler, die nicht greifen während
auf Input von einem Stream gewartet wird - usw. Deshalb (weil PHP) also
keine Threads - wenn ich das ganze Ding in einer anderen Sprache neu
schreibe, dann sind garantiert die Threads der Hauptgrund, sind einfach
zuuuu angenehm.

Ein erster Versuch war bloß auf Performance getrimmt, das habe ich dann
aber aufgegeben weil ich selbst wohl den Code nach ein paar Monaten
nicht mehr verstanden hätte. Also neuer Ansatz, schön objektorientiert,
für jedes eingehende Mail wird ein neues Objekt aufgebaut, welches dann
selbst "weiß", wann es alle nötigen Zeilen enthält - und sich in der DB
verewigt. Oder eben zu dem Schluss kommt, dass der Rest wohl nie mehr
kommen wird - und sich verwerfen lässt.

Threads würden hier einiges einfacher machen, aber was soll's. Der
aktuelle Ansatz ist nicht der optimale - aber es funktioniert. Und das
sogar beeindruckend gut ;-)

Mit liebem Gruß
Thomas Gelf




Mehr Informationen über die Mailingliste Postfixbuch-users