Ich habe eine Anwendung, die jede Transaktion protokollieren muss. Jede Protokollnachricht wird gelöscht, da aufgezeichnet werden muss, was zu einem Absturz geführt hat. Meine Kollegen und ich waren neugierig, wie die Leistungseffekte der Pufferung erzielt werden können, während gleichzeitig sichergestellt wird, dass die Protokollnachricht den Prozess verlassen hat.
Was wir uns ausgedacht haben, ist:
- Erstellen Sie ein FIFO, in das die Anwendung schreiben kann, und
- Leiten Sie den Inhalt dieses FIFO über in eine reguläre Datei um
cat
.
Das heißt, was normalerweise war:
app --logfile logfile.txt
ist jetzt:
mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo
Gibt es Fallstricke bei diesem Ansatz? Es hat funktioniert, als wir es getestet haben, aber wir möchten unbedingt sicherstellen, dass die Nachrichten auch dann in die Umleitungsdatei gelangen, wenn die ursprüngliche Anwendung abstürzt.
(Wir haben keinen Quellcode für die Anwendung, daher kommen Programmierlösungen nicht in Frage. Außerdem schreibt die Anwendung nicht darauf stdout
, sodass eine direkte Weiterleitung an einen anderen Befehl nicht in Frage kommt. Dies syslog
ist also keine Möglichkeit .)
Update: Ich habe ein Kopfgeld hinzugefügt. Die akzeptierte Antwort beinhaltet nichtlogger
den einfachen Grund, logger
nach dem ich nicht gefragt habe. Wie die ursprüngliche Frage besagt, suche ich nur nach Fallstricken bei der Verwendung eines FIFO.
Antworten:
Beachten Sie, dass bei der Programmierung normalerweise ein FIFO erforderlich ist, bei dem der eingegebene Betrag den ausgelesenen Betrag übersteigen kann.
Als solches funktioniert ein Fifo nicht ganz reibungslos, wie Sie es erwarten, sondern würde Ihr Hauptproblem lösen, während Sie ein anderes einführen.
Es gibt drei mögliche Einschränkungen.
Dies bedeutet, dass Ihr Problem (emulierte gepufferte E / A bei einem nicht gepufferten Schreibvorgang emulieren) behoben wird. Dies liegt daran, dass das neue "Limit" für Ihr FIFO tatsächlich die Geschwindigkeit des Dienstprogramms ist, das in der Pipe auf die Festplatte schreibt (was vermutlich gepufferte E / A sein wird).
Trotzdem ist der Schreiber abhängig von Ihrem Protokollleser, um zu funktionieren. Wenn der Leser plötzlich aufhört zu lesen, blockiert der Schreiber. Wenn der Reader plötzlich beendet wird (nehmen wir an, Sie haben nicht mehr genügend Speicherplatz auf Ihrem Ziel), wird der Writer SIGPIPE und wahrscheinlich beendet.
Ein weiterer zu erwähnender Punkt ist, dass Sie bis zu 64.000 Daten in diesem Puffer verlieren können, wenn der Server in Panik gerät und der Kernel nicht mehr reagiert.
Eine andere Möglichkeit, dies zu beheben, besteht darin, Protokolle in tmpfs (/ dev / shm unter Linux) zu schreiben und die Ausgabe an einen festen Speicherort zu senden. Es gibt weniger restriktive Beschränkungen für die Speicherzuweisung (nicht 64 KB, normalerweise 2 GB!), Funktioniert jedoch möglicherweise nicht für Sie, wenn der Writer keine dynamische Möglichkeit zum erneuten Öffnen von Protokolldateien hat (Sie müssten die Protokolle regelmäßig von tmpfs bereinigen). Wenn der Server bei dieser Methode in Panik gerät, können Sie VIEL mehr Daten verlieren.
quelle
/dev/shm
. Wir hatten auch darüber nachgedacht, obwohl es mir durch den Kopf gegangen war, es zu benutzentail -f
.Was passiert, wenn Ihr
cat logfifo
Prozess stirbt, jemand ihn versehentlich tötet oder jemand ihn versehentlich auf den falschen Ort zeigt?Meine Erfahrung ist, dass die
app
schnell blockieren und hängen. Ich habe dies mit Tomcat, Apache und einigen kleinen selbst erstellten Anwendungen versucht und bin auf dasselbe Problem gestoßen. Ich habe nie sehr weit nachgeforscht, weillogger
oder eine einfache E / A-Umleitung das getan hat, was ich will. Normalerweise brauche ich die Vollständigkeit der Protokollierung nicht, was Sie anstreben. Und wie Sie sagen, Sie wollen keinen Logger.Es gibt einige Diskussionen zu diesem Problem bei nicht blockierendem Linux-Fifo (On-Demand-Protokollierung) .
quelle
Ihre Optionen sind durch die App ziemlich eingeschränkt, aber was Sie getestet haben, wird funktionieren.
Wir machen etwas Ähnliches mit Lack und Varnishncsa, um Protokolle an einem für uns nützlichen Ort abzurufen. Wir haben ein Fifo und lesen es einfach mit syslog-ng und senden es dorthin, wo wir es brauchen. Wir verarbeiten ungefähr 50 GB und sind bisher auf kein Problem mit diesem Ansatz gestoßen
quelle
Die Umgebung ist CentOS und die Anwendung schreibt in eine Datei ...
Anstatt an eine reguläre Datei zu senden, würde ich die Ausgabe an syslog senden und sicherstellen, dass Syslog-Nachrichten sowohl an einen zentralen Server als auch lokal gesendet werden.
Sie sollten in der Lage sein, ein Shell-Skript wie das folgende zu verwenden:
Sie können auch Eingaben
logger
voncat
oder nachtail -f
in eine Pipe übernehmen:Das einzige Problem ist, dass es nicht nach der Wichtigkeit der Protokollnachricht differenziert (alles ist HINWEIS ), sondern zumindest protokolliert und auch außerhalb des Hosts an einen zentralen Server gesendet wird.
Die Konfiguration von Syslog hängt davon ab, welchen Server Sie verwenden. Es gibt
rsyslog
undsyslog-ng
(beide sehr fähig).BEARBEITEN : Überarbeitet, nachdem weitere Informationen vom Poster erhalten wurden.
quelle
stdout
. Das Betriebssystem ist CentOS (ich hatte die Frage als Linux markiert , aber ich denke, das ist leicht zu übersehen). Alle Nachrichten sind gleich wichtig, daher gibt es in dieser Anwendung keinen Unterschied zwischen einem Hinweis und einem Fehler.Slow query detected
undDatabase halted
?Du schreibst:
Haben Sie versucht, sich in der "Datei"
/dev/stdout
anzumelden? Das könnte Ihnen Folgendes ermöglichen:quelle
Es macht keinen Sinn, in ein Fifo zu schreiben und es dann von einem anderen Prozess in eine Datei schreiben zu lassen. Schreiben Sie einfach direkt in die Datei und sobald die
write()
Rückkehr erfolgt, liegt sie in den Händen des Kernels. Es wird weiterhin auf die Festplatte geschrieben, wenn die Anwendung abstürzt.quelle
fsync()
wartet, bis jeder Schreibvorgang auf die Festplatte gelangt , und Sie möchten nicht, dass dies geschieht (riskieren Sie einen Verlust im Falle eines Systemabsturzes)?write()
, kann die App nach der Rückkehr nach Belieben abstürzen - die Daten gelangen auf die Festplatte, solange der Kernel nicht abstürzt.