Як використовувати Spring Boot 3.4 для поширення трасувань із користувацьких заголовків

Temp mail SuperHeros
Як використовувати Spring Boot 3.4 для поширення трасувань із користувацьких заголовків
Як використовувати Spring Boot 3.4 для поширення трасувань із користувацьких заголовків

Обробка користувацьких трасувань заголовків у Spring Boot 3.4

Уявіть, що у вас є веб-служба Spring Boot 3.4, яка без проблем працює з двома клієнтами. Перший клієнт використовує Spring Boot 3+, що робить розповсюдження трасування легким. Без додаткових зусиль ви отримуєте чудову наскрізну безперервність трасування 🪄. Колоди виглядають чистими та з’єднаними, немов за помахом чарівної палички.

Однак ситуація змінюється, коли в гру вступає клієнт два. Замість стандартних заголовків трасування вони надсилають спеціальні заголовки, наприклад `ot-custom-traceid` і `ot-custom-spanid`. Хоча ці спеціальні заголовки містять дійсну інформацію трасування, Spring Boot не може поширити ці трасування. Результат? Ви втрачаєте можливість підключати трасування клієнта до журналів на сервері.

Це створює розрив у спостережуваності. Для клієнта ви бачите повний шлях запиту між службами. Для другого клієнта ви бачите лише журнали на стороні сервера, відсутня критична трасування клієнта. Це ніби побачити половину головоломки — ти знаєш, що чогось не вистачає, але не можеш зібрати шматки разом. 😓

У цій статті ми розглянемо, як вирішити цю проблему не покладаючись на Spring Cloud Sleuth, залишаючись вірними екосистемі Spring Boot 3.4. Зрештою, ви знатимете, як поширювати та продовжувати трасування з користувацьких заголовків, забезпечуючи безперебійне спостереження у вашій системі.

Команда Приклад використання
MDC.put Ця команда додає пари ключ-значення до Відображеного діагностичного контексту (MDC), що дозволяє включати ідентифікатори трасування в журнали. Наприклад, MDC.put("traceId", "12345").
MDC.clear Очищає всі записи з MDC після обробки запиту, щоб уникнути забруднення слідів між запитами. Наприклад, MDC.clear().
OncePerRequestFilter Фільтр Spring Boot, який гарантує, що логіка фільтра виконується лише один раз на запит HTTP, що ідеально підходить для трасування заголовків. Приклад: відкритий клас CustomTraceFilter розширює OncePerRequestFilter.
filterChain.doFilter Переходить до наступного фільтра в ланцюжку, гарантуючи, що запит продовжується через інші фільтри. Наприклад, filterChain.doFilter(запит, відповідь).
RestTemplate.getInterceptors() Отримує список перехоплювачів для екземпляра RestTemplate, що дозволяє додавати спеціальні перехоплювачі. Приклад: restTemplate.getInterceptors().add(new CustomInterceptor()).
ClientHttpRequestInterceptor Інтерфейс для перехоплення вихідних HTTP-запитів і додавання спеціальних заголовків. Наприклад, реалізація ClientHttpRequestInterceptor для вставки ідентифікаторів трасування.
HttpServletRequest.getHeader Витягує значення конкретного HTTP-заголовка з вхідного запиту. Приклад: request.getHeader("ot-custom-traceid").
FilterRegistrationBean Реєструє спеціальні фільтри в програмі Spring Boot. Наприклад: registrationBean.setFilter(new CustomTraceFilter()).
MockMvc.perform Імітує HTTP-запити в модульних тестах для програм Spring Boot. Приклад: mockMvc.perform(get("/test-endpoint").header("ot-custom-traceid", "12345")).
ClientHttpRequestExecution.execute Виконує перехоплений HTTP-запит із наданим тілом запиту та заголовками. Приклад: execution.execute(request, body).

Спеціальне розповсюдження трасування заголовка під час завантаження Spring

Одним із ключових компонентів у вирішенні цієї проблеми є CustomTraceFilter. Цей фільтр розширює OncePerRequestFilter класу, гарантуючи, що логіка заголовка трасування виконується лише один раз для кожного запиту HTTP. Фільтри у Spring Boot неймовірно корисні під час глобального модифікування запитів або відповідей. Наприклад, якщо клієнт надсилає інформацію про відстеження, наприклад ot-custom-traceid або от-звичай-спанид у спеціальних заголовках цей фільтр перехоплює запит, витягує ці заголовки та поширює їх у Відображений діагностичний контекст (MDC). Додаючи ідентифікатори трасування до MDC, ми забезпечуємо відображення цих ідентифікаторів у журналах, створених під час обробки запиту.

MDC є важливою частиною фреймворків журналювання, таких як SLF4J і Logback. Це дозволяє нам зберігати контекстну інформацію для поточного потоку, таку як власні ідентифікатори трасування. Використання таких команд, як MDC.пут і MDC.clear, ми гарантуємо, що система журналювання містить деталі трасування та уникає зараження між одночасними запитами. Наприклад, якщо клієнт два надсилає `ot-custom-traceid` як `8f7ebd8a73f9a8f50e6a00a87a20952a`, цей ідентифікатор зберігається в MDC і включається в усі подальші журнали, створюючи послідовний шлях трасування.

З іншого боку, для вихідних HTTP-запитів перехоплювач RestTemplate відіграє важливу роль. Шляхом реалізації ClientHttpRequestInterceptor, ми можемо додавати ті самі заголовки трасування (`ot-custom-traceid` і `ot-custom-spanid`) до вихідних запитів. Це гарантує безперервність трасування, коли програма викликає інші мікросервіси. Наприклад, коли сервер обробляє запит із ідентифікатором трасування `8f7ebd8a73f9a8f50e6a00a87a20952a`, він прикріплює цей ідентифікатор до вихідних заголовків, щоб нижчі служби могли розпізнавати та безперешкодно поширювати трасування.

Нарешті, модульні тести, написані за допомогою MockMvc, перевіряють усі налаштування шляхом імітації HTTP-запитів і перевірки поширення заголовка. У реальних програмах тестування має вирішальне значення для забезпечення правильної обробки заголовків трасування. Наприклад, надіславши запит GET із спеціальними заголовками та перевіривши відповідь або журнали, ми можемо підтвердити, що фільтр і перехоплювач працюють належним чином. Цей комплексний підхід вирішує проблему, не покладаючись на застарілі залежності, такі як Spring Cloud Sleuth. Зрештою, поєднання фільтрів, перехоплювачів і MDC забезпечує безперервність трасування, навіть коли клієнти використовують спеціальні заголовки, роблячи систему надійною та повністю доступною для спостереження. 🌟

Розповсюдження користувацьких заголовків трасування у Spring Boot 3.4

Використання Java із Spring Boot 3.4 і Micrometer для серверної обробки

// Solution 1: Extract and Propagate Custom Trace Headers Manually
// Import necessary Spring Boot and Micrometer libraries
import org.slf4j.MDC;
import org.springframework.http.HttpHeaders;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CustomTraceFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws IOException {
        String traceId = request.getHeader("ot-custom-traceid");
        String spanId = request.getHeader("ot-custom-spanid");
        try {
            if (traceId != null) {
                MDC.put("traceId", traceId); // Add traceId to Mapped Diagnostic Context
            }
            if (spanId != null) {
                MDC.put("spanId", spanId);
            }
            filterChain.doFilter(request, response); // Continue request processing
        } finally {
            MDC.clear(); // Ensure MDC is cleared after processing
        }
    }
}

// Register the filter in your configuration class
@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<CustomTraceFilter> traceFilter() {
        FilterRegistrationBean<CustomTraceFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new CustomTraceFilter());
        registrationBean.addUrlPatterns("/*");
        return registrationBean;
    }
}

Модульний тест для власного розповсюдження заголовка трасування

Тестування за допомогою JUnit і MockMvc для перевірки поширення заголовка трасування

// Import necessary libraries
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest
public class CustomTraceFilterTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testCustomTraceHeaders() throws Exception {
        mockMvc.perform(get("/test-endpoint")
                .header("ot-custom-traceid", "12345")
                .header("ot-custom-spanid", "67890"))
                .andExpect(status().isOk());
    }
}

Розповсюдження настроюваних заголовків у HTTP-запитах за допомогою RestTemplate

Використання перехоплювачів RestTemplate для додавання спеціальних заголовків у вихідні запити

// Import necessary libraries
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;

public class CustomHeaderInterceptor implements ClientHttpRequestInterceptor {
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        HttpHeaders headers = request.getHeaders();
        headers.add("ot-custom-traceid", "12345");
        headers.add("ot-custom-spanid", "67890");
        return execution.execute(request, body);
    }
}

// Register the interceptor with RestTemplate
@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getInterceptors().add(new CustomHeaderInterceptor());
        return restTemplate;
    }
}

Обробка спеціальних трасувань заголовків за допомогою OpenTelemetry у Spring Boot 3.4

Під час роботи з Spring Boot 3.4 ще одним потужним підходом до розповсюдження трасування з настроюваних заголовків є інтеграція OpenTelemetry. OpenTelemetry, платформа спостереження з відкритим кодом, допомагає легко інструментувати, збирати та експортувати траси. Він надає механізми для вилучення та введення контексту трасування, включаючи спеціальні заголовки, такі як ot-custom-traceid і от-звичай-спанид, у вашу програму. Використовуючи TextMapPropagator OpenTelemetry, ви можете подолати розрив між нестандартними клієнтами та вашою системою спостереження.

Щоб використовувати OpenTelemetry у Spring Boot 3.4, можна реалізувати настроюваний пропагатор, щоб отримати інформацію трасування з користувацьких заголовків і приєднати її до поточного контексту трасування. Наприклад, коли ваш сервер отримує вхідний запит від другого клієнта, OpenTelemetry може проаналізувати спеціальні заголовки та реконструювати вихідний контекст трасування. Це гарантує, що низхідні служби бачать однакові ідентифікатори трасування, забезпечуючи наскрізну видимість. На відміну від старіших рішень, таких як Spring Cloud Sleuth, OpenTelemetry легкий і відповідає сучасним стандартам спостереження.

Поєднавши пропагатор OpenTelemetry з Micrometer, ви можете збагатити свої показники та журнали інформацією трасування. Уявіть, що ви безперебійно бачите відстеження запитів, що надходять як від Клієнта один, так і від Клієнта два у вашому інструменті спостереження. OpenTelemetry автоматично підтримує інтеграцію з Prometheus, Zipkin або Jaeger, що дозволяє централізувати візуалізацію трасування. Цей підхід гарантує, що навіть якщо задіяні спеціальні заголовки, дані трасування не втрачаються, а налагодження стає значно легшим. 🚀

Поширені запитання щодо розповсюдження власних трасувань у Spring Boot

  1. Як вручну витягти власні заголовки трасування у Spring Boot?
  2. Ви можете використовувати request.getHeader("custom-header"), щоб вручну отримати певний заголовок і додати його до MDC за допомогою MDC.put("traceId", value).
  3. Які переваги використання OpenTelemetry для розповсюдження настроюваного трасування?
  4. OpenTelemetry забезпечує сучасний, нейтральний від постачальника підхід до розповсюдження трасування, включаючи спеціальні заголовки, між мікросервісами.
  5. Чи можу я поширювати власні заголовки за допомогою RestTemplate у Spring Boot?
  6. Так, реалізувавши ClientHttpRequestInterceptor, ви можете додавати спеціальні заголовки, як-от traceid і spanid, до вихідних запитів.
  7. Як зареєструвати фільтр для глобального захоплення заголовків?
  8. Ви можете створити фільтр, який розширює OncePerRequestFilter, і зареєструвати його за допомогою FilterRegistrationBean для захоплення заголовків для всіх кінцевих точок.
  9. Які інструменти я можу використовувати для візуалізації слідів із Spring Boot?
  10. Такі інструменти, як Zipkin, Jaeger і Prometheus, можна інтегрувати з Spring Boot і OpenTelemetry для візуалізації наскрізних трас.

Забезпечення безперебійної трасування

У сучасних системах обробка настроюваних заголовків трасування має вирішальне значення для надійної спостережуваності. Використовуючи фільтри та перехоплювачі, ви можете отримувати інформацію про відстеження, надану клієнтом, і правильно поширювати її між вашими службами. Це дозволяє уникнути фрагментованих журналів і відсутніх слідів. 🔍

Spring Boot 3.4 у поєднанні з Micrometer або OpenTelemetry дозволяє створювати надійні рішення, не покладаючись на старіші інструменти, такі як Spring Cloud Sleuth. Незалежно від того, чи маєте ви справу зі стандартними заголовками Клієнта 1 чи користувацькими заголовками Клієнта 2, впровадження цих методів ефективно заповнює пропуски в трасуванні. 🚀

Джерела та література
  1. Офіційна документація Spring Boot: розповсюдження контекстів трасування. Документація Spring Boot
  2. OpenTelemetry для розробників Java: посібник із поширення трасування. OpenTelemetry Java
  3. Документація щодо спостережуваності мікрометрів: інтеграція користувацьких заголовків трас. Мікрометрична спостережливість
  4. API журналювання SLF4J: приклади використання відображеного діагностичного контексту (MDC). SLF4J Посібник