Spring Web MVC, das häufig in Spring verwendet wird, tritt dieses Problem nicht auf.
Der Hauptunterschied zwischen WebFlux und WebMVC besteht in der Behandlung von Threads bei der Verarbeitung von Anforderungen und Antworten. Event Loop Thread, das in WebFlux verwendet wird, unterscheidet sich von Spring MVC darin, dass eine Anforderung von mehreren Threads verarbeitet wird.
Die Implementierung von MDC hängt jedoch von LocalThread ab. Mit anderen Worten, der Thread, der den MDC ausgeführt hat, verfügt über die MDC-Informationen, aber der Thread, der nicht über die MDC-Informationen verfügt, ist nicht vorhanden und wird nicht im Protokoll angezeigt.
Ich habe dieses Ereignis in der letzten Minute der ** Produktionsveröffentlichung ** durchlaufen, und hier sind die Ergebnisse dieser Untersuchung.
In den beiden obigen Abschnitten wird beschrieben, wie MDC mit WebFlux zwischen mehreren Anwendungen weitergegeben wird. Dies ist ein Schritt weiter als dieses Thema. Ich möchte dies in Separater Artikel untersuchen.
Die Antwort finden Sie im nächsten Artikel
Es gibt eine Funktion namens Kontext und drei Methoden, "logOnNext", "logOnError" und "put". Der Kontext hier ist übrigens der Kontext von Reactor. Weitere Informationen finden Sie in this, das in Reactor als Dokument beschrieben ist.
Einfach ausgedrückt ist der Kontext ein Mechanismus, mit dem "** Daten in einer reaktiven Umgebung verbreiten kann **", mit dem MDC ordnungsgemäß funktioniert. (Es scheint, dass der Mechanismus zur Weitergabe von Abonnements an der Weitergabe von Daten beteiligt ist, und ich verstehe ihn bis zu diesem Punkt nicht, aber das obige Dokument 9.8.2 enthält eine ähnliche Erklärung!)
Da es als Artikel nicht sehr wertvoll ist, werde ich mich mit jeder Methode befassen.
--LogHelper.java
definiertpublic static final String CONTEXT_MAP = "context-map";
.
--logOnNext
und logOnError
beziehen sich auf den Kontext durch den Schlüsselwert der Konstante CONTEXT_MAP
. Da der Kontext eine I / F-ähnliche Karte hat, nimmt er den Wert auf. Es schiebt es in den MDC, gibt ein Protokoll aus und löscht den MDC, wenn der Betrieb beendet ist.
--put
schreibt mit der Konstante CONTEXT_MAP
in den Kontext.
LogHelper.java
public static <T> Consumer<Signal<T>> logOnNext(
Consumer<T> log) {
return signal -> {
if (signal.getType() != SignalType.ON_NEXT) return;
Optional<Map<String, String>> maybeContextMap
= signal.getContext().getOrEmpty(CONTEXT_MAP);
if (maybeContextMap.isEmpty()) {
log.accept(signal.get());
} else {
MDC.setContextMap(maybeContextMap.get());
try {
log.accept(signal.get());
} finally {
MDC.clear();
}
}
};
logOnNext
wird in Kombination mit der doOnEach
-Methode von WebFlux verwendet.
signal.getType ()! = SignalType.ON_NEXT
ist ein Miso, und diese Methode reagiert nicht, wenn ein abnormales System aufgerufen wird. Es wird gezündet und protokolliert, wenn sich die Daten normal verbreiten.
LogHelper.java
public static <T> Consumer<Signal<T>> logOnError(
Consumer<Throwable> log) {
return signal -> {
if (!signal.isOnError()) return;
Optional<Map<String, String>> maybeContextMap
= signal.getContext().getOrEmpty(CONTEXT_MAP);
if (maybeContextMap.isEmpty()) {
log.accept(signal.getThrowable());
} else {
MDC.setContextMap(maybeContextMap.get());
try {
log.accept(signal.getThrowable());
} finally {
MDC.clear();
}
}
};
}
Der Umriss von "logOnError" unterscheidet sich nicht wesentlich von dem von "logOnNext". Das zu referenzierende Signal hat sich jedoch geändert und protokolliert als Reaktion auf das Fehlersignal.
Mit anderen Worten, wenn Sie am Ende einer Methode logOnXXX
verwenden, wird Error nicht aufgerufen, wenn es normal endet, und Next wird nicht aufgerufen, wenn es abnormal endet.
LogHelper.java
public static Function<Context, Context> put(String key, String value) {
return ctx -> {
Optional<Map<String, String>> maybeContextMap =
ctx.getOrEmpty(CONTEXT_MAP);
if (maybeContextMap.isPresent()) {
maybeContextMap.get().put(key, value);
return ctx;
} else {
Map<String, String> ctxMap = new HashMap<>();
ctxMap.put(key, value);
return ctx.put(CONTEXT_MAP, ctxMap);
}
};
Die Rolle von "put" ist unkompliziert, es werden nur die Daten im Kontext gespeichert. Die Verwendungsmethode ist wie folgt.
.subscriberContext(put("hogehogeId", response.getHogehogeId().toString()))
subscriberContext ist eine Reihe von Prozessen, soweit das Dokument angezeigt wird. Es scheint den Kontext in zu erzeugen. put nimmt auf und fügt die Konstante "CONTEXT" hinzu und gibt einen neuen Kontext zurück, sodass Sie innerhalb der Kette der Datenausbreitung endlos Werte in den MDC eintauchen können.
Ist es überhaupt unmöglich, MDC in einer reaktiven Umgebung einzusetzen? Bitte lassen Sie mich wissen, ob es einen guten Weg gibt.
Recommended Posts