التعامل مع آثار الرأس المخصصة في 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 تمتد إلى OnePerRequestFilter. |
filterChain.doFilter | ينتقل إلى عامل التصفية التالي في السلسلة، مما يضمن استمرار الطلب من خلال عوامل التصفية الأخرى. على سبيل المثال، filterChain.doFilter(request, Response). |
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 الذي تم اعتراضه باستخدام نص الطلب ورؤوسه المقدمة. مثال: Execute.execute(request, body). |
نشر تتبع الرأس المخصص في Spring Boot
أحد المكونات الرئيسية لحل هذه المشكلة هو CustomTraceFilter. يعمل هذا الفلتر على توسيع OnePerRequestFilter فئة، مما يضمن تشغيل منطق رأس التتبع مرة واحدة فقط لكل طلب HTTP. تعد المرشحات في Spring Boot مفيدة بشكل لا يصدق عند تعديل الطلبات أو الاستجابات على مستوى العالم. على سبيل المثال، إذا أرسل العميل معلومات التتبع مثل ot-custom-traceid أو بعد ذلك مخصص الأسبانية في الرؤوس المخصصة، يعترض عامل التصفية هذا الطلب، ويستخرج هذه الرؤوس، وينشرها في سياق التشخيص المعين (MDC). ومن خلال إضافة معرفات التتبع إلى MDC، فإننا نضمن أن هذه المعرفات مرئية في السجلات التي تم إنشاؤها أثناء معالجة الطلب.
يعد MDC جزءًا مهمًا من أطر عمل التسجيل مثل SLF4J وLogback. فهو يسمح لنا بتخزين المعلومات السياقية للسلسلة الحالية، مثل معرفات التتبع المخصصة. باستخدام أوامر مثل MDC.put و MDC. واضحنحن نضمن أن نظام التسجيل يتضمن تفاصيل التتبع ويتجنب التلوث بين الطلبات المتزامنة. على سبيل المثال، إذا أرسل العميل الثاني "ot-custom-traceid" كـ "8f7ebd8a73f9a8f50e6a00a87a20952a"، فسيتم تخزين هذا المعرف في MDC ويتم تضمينه في كافة السجلات النهائية، مما يؤدي إلى إنشاء مسار تتبع متسق.
من ناحية أخرى، بالنسبة لطلبات HTTP الصادرة، يلعب RestTemplate Interceptor دورًا أساسيًا. بالتنفيذ 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 Interceptors لإضافة رؤوس مخصصة في الطلبات الصادرة
// 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، وهو إطار عمل مفتوح المصدر لإمكانية المراقبة، على تحديد الآثار وجمعها وتصديرها بسلاسة. فهو يوفر آليات لاستخراج سياق التتبع وإدخاله، بما في ذلك الرؤوس المخصصة مثل ot-custom-traceid و بعد ذلك مخصص الأسبانية، في التطبيق الخاص بك. من خلال الاستفادة من TextMapPropagator من OpenTelemetry، يمكنك سد الفجوة بين العملاء غير القياسيين ونظام إمكانية المراقبة الخاص بك.
لاستخدام OpenTelemetry في Spring Boot 3.4، يمكن تنفيذ ناشر مخصص لاستخراج معلومات التتبع من الرؤوس المخصصة وإرفاقها بسياق التتبع الحالي. على سبيل المثال، عندما يتلقى الخادم الخاص بك طلبًا واردًا من Client Two، يمكن لـ OpenTelemetry تحليل الرؤوس المخصصة وإعادة بناء سياق التتبع الأصلي. وهذا يضمن أن الخدمات النهائية ترى نفس معرفات التتبع، مما يسمح بالرؤية الشاملة. على عكس الحلول القديمة مثل Spring Cloud Sleuth، فإن OpenTelemetry خفيف الوزن ويتوافق مع معايير إمكانية المراقبة الحديثة.
من خلال الجمع بين أداة نشر OpenTelemetry وMicometer، يمكنك إثراء المقاييس والتسجيل بمعلومات التتبع. تخيل أنك ترى آثارًا للطلبات الواردة من كل من Client One وClient Two بسلاسة في أداة المراقبة لديك. يدعم OpenTelemetry عمليات التكامل تلقائيًا مع Prometheus أو Zipkin أو Jaeger، مما يتيح لك مركزية تصور التتبع. يضمن هذا الأسلوب أنه حتى عند استخدام الرؤوس المخصصة، لن يتم فقدان أي بيانات تتبع، وسيصبح تصحيح الأخطاء أسهل بكثير. 🚀
الأسئلة المتداولة حول نشر الآثار المخصصة في Spring Boot
- كيف يمكنني استخراج رؤوس التتبع المخصصة يدويًا في Spring Boot؟
- يمكنك استخدام request.getHeader("custom-header") لجلب رأس محدد يدويًا وإضافته إلى MDC باستخدام MDC.put("traceId", value).
- ما فائدة استخدام OpenTelemetry لنشر التتبع المخصص؟
- يوفر OpenTelemetry أسلوبًا حديثًا ومحايدًا للبائع لنشر التتبعات، بما في ذلك الرؤوس المخصصة، عبر الخدمات الصغيرة.
- هل يمكنني نشر الرؤوس المخصصة باستخدام RestTemplate في Spring Boot؟
- نعم، من خلال تنفيذ ClientHttpRequestInterceptor، يمكنك إرفاق رؤوس مخصصة مثل traceid و spanid للطلبات الصادرة.
- كيف يمكنني تسجيل مرشح لالتقاط الرؤوس عالميًا؟
- يمكنك إنشاء مرشح يمتد OncePerRequestFilter وتسجيله باستخدام FilterRegistrationBean لالتقاط الرؤوس لجميع نقاط النهاية.
- ما الأدوات التي يمكنني استخدامها لتصور الآثار من Spring Boot؟
- يمكن لأدوات مثل Zipkin وJaeger وPrometheus أن تتكامل مع Spring Boot وOpenTelemetry لتصور الآثار الشاملة.
ضمان استمرارية التتبع السلس
في الأنظمة الحديثة، يعد التعامل مع رؤوس التتبع المخصصة أمرًا بالغ الأهمية لضمان إمكانية المراقبة الموثوقة. باستخدام عوامل التصفية والأدوات الاعتراضية، يمكنك التقاط معلومات التتبع المقدمة من العميل ونشرها بشكل صحيح عبر خدماتك. يؤدي هذا إلى تجنب السجلات المجزأة والآثار المفقودة. 🔍
يتيح Spring Boot 3.4، جنبًا إلى جنب مع Micrometer أو OpenTelemetry، حلولاً قوية دون الاعتماد على الأدوات القديمة مثل Spring Cloud Sleuth. سواء كنت تتعامل مع الرؤوس القياسية الخاصة بـ Client One أو الرؤوس المخصصة لـ Client Two، فإن تنفيذ هذه التقنيات يعمل على سد فجوات التتبع بكفاءة. 🚀
المصادر والمراجع
- التوثيق الرسمي لـ Spring Boot: نشر سياقات التتبع. وثائق التمهيد الربيع
- القياس عن بعد المفتوح لمطوري جافا: دليل لتتبع الانتشار. جافا القياس عن بعد المفتوحة
- توثيق إمكانية ملاحظة الميكرومتر: دمج رؤوس التتبع المخصصة. إمكانية ملاحظة الميكرومتر
- واجهة برمجة تطبيقات تسجيل SLF4J: حالات استخدام السياق التشخيصي المعين (MDC). دليل SLF4J