Files
digital-garden/dev/java/quarkus/Обеспечение корректного асинхронного выполнения в Quarkus.md
Struchkov Mark ee66c043b8
All checks were successful
continuous-integration/drone/push Build is passing
Обновление
2025-02-25 21:32:31 +03:00

57 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
aliases:
tags:
- maturity/🌱
- content/problem
date: 2025-02-24
---
В процессе разработки одного из сервисов я обнаружил, что при асинхронной обработке данных с почтового сервера терялась диагностическая информация, передаваемая через [[../../Mapped Diagnostic Context|MDC]].
Первоначально код выглядел как-то так:
```java
Unis.voidItem()
.chain(() -> mailService.process(msg));
```
**Возникающие проблемы:**
- **Потеря MDC:** MDC хранится в ThreadLocal, а асинхронные операции могут переключаться между потоками. Из-за этого данные, установленные в MDC, терялись или оказывались перепутанными, что усложняло диагностику.
- **Отсутствие изоляции:** Поскольку вызов выполнялся в общем контексте, отсутствовало явное управление окружением выполнения. Это могло привести к состояниям гонки или другим непредсказуемым ошибкам.
- Блокировка [[../../architecture/Event Loop|event loop]]: Если метод `mailService.process` выполнял блокирующий код, это могло негативно сказаться на производительности.
Стоит подчеркнуть, что если бы запрос поступал через стандартные механизмы [[../../../meta/zero/00 Quarkus|Quarkus]] (gRPC, GraphQL, Kafka), то управление контекстом осуществлялось бы системой, и подобных проблем бы не возникало. Однако в нашем случае вызов инициировался через `org.apache.camel.Processor`, что требовало дополнительных усилий по сохранению контекстной информации.
Анализ показал, что основная проблема кроется в потере MDC при переключении между потоками. В условиях асинхронного выполнения вызовы, инициированные через Camel, не гарантируют автоматическую передачу контекста, что приводит к потере данных, необходимых для корректного логирования и диагностики.
==Чтобы решить эту проблему, было решено явно создать дублированный контекст и переключить выполнение на него.== Код был изменён следующим образом:
```java
final Context duplicateContext = Context.newInstance(
VertxContext.getOrCreateDuplicatedContext(vertx.getDelegate())
);
Unis.voidItem()
.emitOn(duplicateContext::runOnContext)
.chain(() -> mailService.process(msg));
```
**Преимущества данного подхода:**
- **Сохранение MDC:** Дублированный контекст позволяет перенести все данные, связанные с текущим окружением (включая MDC), что обеспечивает корректное логирование даже при асинхронном выполнении.
- **Изоляция выполнения:** Переключение на новый контекст гарантирует, что все последующие операции выполняются в заданном окружении, исключая неожиданные переключения потоков.
- Устранение блокировки [[../../architecture/Event Loop|event loop]]: Если метод `mailService.process` содержит блокирующие или ресурсоёмкие операции, их выполнение в изолированном контексте помогает снизить негативное влияние на основной event loop.
Таким образом, если ваши асинхронные операции инициируются через нестандартные компоненты, такие как Apache Camel, и Quarkus не управляет контекстом напрямую, создание дублированного контекста становится необходимым для корректной работы.
***
## Мета информация
**Область**:: [[../../../meta/zero/00 Quarkus|00 Quarkus]]
**Родитель**::
**Источник**::
**Создана**:: [[2025-02-24]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->