Проблемы параллелизма в отслеживании перехватчиков MDC

У меня есть следующий перехватчик, который отслеживает запрос / ответ на основе сохранения и восстановления некоторых переменных, хранящихся в контексте MDC для каждого запроса.

public class LoggingInterceptor implements DeferredResultProcessingInterceptor {
    private final HelloSeeYouLogger helloSeeYouLogger;
    private static final String X_UOW = "X-UOW";
    private static final String X_REQUEST_ID = "X-RequestId";
    private Map<String, String> context;

    public LoggingInterceptor(HelloSeeYouLogger helloSeeYouLogger) {
        this.helloSeeYouLogger = helloSeeYouLogger;
    }

    @Override
    public <T> void beforeConcurrentHandling(NativeWebRequest request, DeferredResult<T> deferredResult) {
        addUowAndRequestIdToMDC(request.getHeader(X_UOW), request.getHeader(X_REQUEST_ID));
        final String uri = getUri((HttpServletRequest) request.getNativeRequest());
        helloSeeYouLogger.logHelloThere(uri);
        context = MDC.getCopyOfContextMap();
    }

    @Override
    public <T> void afterCompletion(NativeWebRequest request, DeferredResult<T> deferredResult) {
        if (context != null) {
            MDC.setContextMap(context);
        }
        final String uri = getUri((HttpServletRequest) request.getNativeRequest());
        String body = getBody((HttpServletRequest) request.getNativeRequest());
        if (!StringUtils.isEmpty(body)) {
            body = replaceMoreThanOneSpacesWithOneSpace(hideCreditCardNumber(body));
        }
        helloSeeYouLogger.logSeeYou(uri, body);
        clearUowAndRequestIdFromMDC();
    }

public static void addUowAndRequestIdToMDC(final String uow, final String requestId) {
        //This NewRelic stuff shouldn't be here as it is used for distributed tracing and not logging.
        // However it helps to levarage requests tracking from a metric service such as new relic to a log aggregation service
        //such as ELK.
        NewRelic.addCustomParameter(UOW, uow);
        NewRelic.addCustomParameter(REQUEST_ID, requestId);
        MDC.put(UOW, uow);
        MDC.put(REQUEST_ID, requestId);
    }

    public static void clearUowAndRequestIdFromMDC() {
        if (MDC.get(UOW) != null) {
            MDC.remove(UOW);
        }

        if (MDC.get(REQUEST_ID) != null) {
            MDC.remove(REQUEST_ID);
        }
    }

Я думаю, что у меня будут проблемы с параллелизмом, так как контекст является переменной экземпляра, и при запуске нескольких параллельных потоков сохранение и восстановление контекста MDC приведет к неверным результатам. Также использование ключевого слова синхронизации добавит проблемы с производительностью. Мне было интересно, если есть лучший подход для отслеживания контекста MDC, когда пружинный контроллер возвращает DeferredResult.

Спасибо

0 ответов

Вы можете использовать попробуйте использовать HandlerInterceptorAdapter вместо

Проверьте: https://www.logicbig.com/how-to/code-snippets/jcode-spring-mvc-deferredresultprocessinginterceptor.html

Другие вопросы по тегам