In unserer Software verwenden wir MDC ausgiebig, um beispielsweise Sitzungs-IDs und Benutzernamen für Webanfragen zu verfolgen. Dies funktioniert gut, wenn Sie im ursprünglichen Thread ausgeführt werden. Es gibt jedoch viele Dinge, die im Hintergrund verarbeitet werden müssen. Dafür verwenden wir die Klassen java.concurrent.ThreadPoolExecutor
und java.util.Timer
zusammen mit einigen selbst gerollten asynchronen Ausführungsdiensten. Alle diese Dienste verwalten ihren eigenen Thread-Pool.
Dies ist, was das Handbuch von Logback über die Verwendung von MDC in einer solchen Umgebung zu sagen hat:
Eine Kopie des zugeordneten Diagnosekontexts kann nicht immer von Arbeitsthreads vom initiierenden Thread geerbt werden. Dies ist der Fall, wenn java.util.concurrent.Executors für die Thread-Verwaltung verwendet wird. Beispielsweise erstellt die newCachedThreadPool-Methode einen ThreadPoolExecutor und verfügt wie anderer Thread-Pooling-Code über eine komplexe Thread-Erstellungslogik.
In solchen Fällen wird empfohlen, MDC.getCopyOfContextMap () für den ursprünglichen (Master-) Thread aufzurufen, bevor eine Aufgabe an den Executor gesendet wird. Wenn die Aufgabe als erste Aktion ausgeführt wird, sollte sie MDC.setContextMapValues () aufrufen, um die gespeicherte Kopie der ursprünglichen MDC-Werte dem neuen von Executor verwalteten Thread zuzuordnen.
Dies wäre in Ordnung, aber es ist sehr leicht zu vergessen, diese Anrufe hinzuzufügen, und es gibt keine einfache Möglichkeit, das Problem zu erkennen, bis es zu spät ist. Das einzige Anzeichen bei Log4j ist, dass Sie fehlende MDC-Informationen in den Protokollen erhalten, und bei Logback erhalten Sie veraltete MDC-Informationen (da der Thread im Laufflächenpool seinen MDC von der ersten Aufgabe erbt, die darauf ausgeführt wurde). Beides sind schwerwiegende Probleme in einem Produktionssystem.
Ich sehe unsere Situation in keiner Weise besonders, aber ich konnte im Web nicht viel über dieses Problem finden. Anscheinend ist dies nicht etwas, gegen das viele Menschen stoßen, also muss es einen Weg geben, dies zu vermeiden. Was machen wir hier falsch?