التسجيل الموزّع ومعرّفات الارتباط
التسجيل الموزّع ومعرّفات الارتباط
عندما يعبر طلب مستخدم واحد عبر خدمة الطلبات وخدمة المخزون وخدمة الإشعارات، تُسجّل ثلاثة ملفات منفصلة ثلاثة أجزاء منفصلة من القصة ذاتها. بدون معرّف مشترك يربط تلك الأجزاء، يعني تصحيح عطل في الإنتاج ربطَ الطوابع الزمنية يدويًا عبر الخدمات — وهي مهمة معرّضة للخطأ قد تستغرق ساعات. تحلّ معرّفات الارتباط هذه المشكلة بإرفاق معرّف فريد بكل طلب عند نقطة الدخول وتمريره عبر كل استدعاء لاحق، بحيث يمكنك البحث بقيمة واحدة وإعادة تجميع التتبع الكامل.
المشكلة بأمثلة ملموسة
افترض أن طلبًا يدخل بوابة API الخاصة بك في الساعة 14:32:01.042. تستدعي البوابة خدمة الطلبات، التي تستدعي المخزون، الذي يستدعي محوّل المستودع. تسجّل كل خدمة أحداثها الخاصة. بدون ارتباط:
- تبحث في سجلات خدمة الطلبات عن بريد المستخدم فتجد ثلاثة سجلات تتطابق مع مستخدمين مختلفين.
- لا يمكنك تحديد استدعاء المخزون الذي ينتمي إلى أيّ استدعاء للطلبات.
- خطأ 503 مدفون في سجل محوّل المستودع يظل غير مرئي ما لم تتفقد ذلك الملف بالصدفة.
بوجود معرّف ارتباط (X-Correlation-ID: a7f3c91b-4d2e-4f8a-b6c1-9e0d3a2b1f5c) في كل سطر سجل، يكشف بحث واحد عبر مُجمّع سجلاتك (Splunk أو Loki أو CloudWatch Insights) كل حدث في السلسلة بأكملها ترتيبًا زمنيًا.
Micrometer Tracing + Brave: مقاربة Spring Boot 3
يشحن Spring Boot 3 مع Micrometer Tracing كتجريد مدمج للتتبع الموزع، يحلّ محل Spring Cloud Sleuth الذي أُهمل. يلفّ Micrometer Tracing جسرًا قابلًا للتبديل — في معظم المشاريع يكون ذلك الجسر هو Brave من بيئة Zipkin. أضف هذه التبعيات إلى كل خدمة في pom.xml:
بهذه التبعيات وحدها، يُهيّئ Spring Boot تلقائيًا كائن Tracer. يحصل كل طلب HTTP وارد تلقائيًا على معرّف التتبع (trace ID) الذي يُعرّف شجرة الطلب الموزعة بأكملها، ومعرّف النطاق (span ID) الذي يُعرّف وحدة العمل الحالية داخل تلك الشجرة. يُدرَج كلاهما في SLF4J MDC تحت مفتاحَي traceId وspanId، ما يجعلهما متاحَين في كل سطر سجل تلقائيًا.
ضبط نمط السجل
حدّث application.yml في كل خدمة ليظهر المعرّفان في كل سطر سجل:
يقرأ التعبير %X{traceId:-} مفتاح MDC باسم traceId؛ واللاحقة :- تعني "سلسلة فارغة إذا غاب" فتُعرض سطور السجل من خيوط الخلفية التي لا تتبع تتبعًا نشطًا بشكل نظيف.
سيبدو سطر السجل الآن هكذا:
نشر التتبع إلى الخدمات اللاحقة
ينشر Micrometer Tracing سياق التتبع تلقائيًا عند استخدام WebClient أو RestClient لأن Spring Boot يُسجّل مرشّح تتبع للتبادل. يجب الحصول على الـ bean الذي يُنشئه Spring Boot — لا تبنِ نسختك الخام:
عندما تستدعي OrderService الخاصة بك كائن inventoryClient، يُضيف Spring تلقائيًا ترويسة b3 (أو ترويسة W3C القياسية traceparent) إلى الطلب الصادر. تقرأ خدمة المخزون تلك الترويسة وتُنشئ نطاقًا فرعيًا وتسجّل بنفس معرّف التتبع. السلسلة بأكملها مرتبطة.
management.tracing.propagation.type=W3C في جميع الخدمات. ترويسة W3C القياسية traceparent هي معيار IETF وتفهمها AWS X-Ray وAzure Monitor وGoogle Cloud Trace مباشرةً. الصيغة القديمة B3 (أسلوب Zipkin) شائعة لكنها أقل دعمًا عالميًا.
إنشاء نطاقات يدوية للعمليات التجارية
تخبرك نطاقات HTTP التلقائية بأن استدعاءً جرى وكم استغرق، لكنها لا تقول شيئًا عمّا حدث داخل منطقك التجاري. أنشئ نطاقات فرعية صريحة للعمليات المهمة:
تُرفق استدعاءات tag() بيانات وصفية قابلة للبحث بالنطاق. عند فتح هذا التتبع في Zipkin أو Grafana Tempo سترى جدولًا زمنيًا مرئيًا يظهر فيه inventory.reserve متداخلًا تحت نطاق HTTP مُعلَّمًا بمعرّف المنتج والنتيجة.
إضافة ترويسة معرّف ارتباط مخصّص
أحيانًا تحتاج إلى معرّف ارتباط على مستوى الأعمال يُرسله عملاؤك أو شركاؤك — مثلاً بوابة دفع ترسل X-Payment-Reference يجب أن يظهر في كل سجل يتعلق بتلك الدفعة. يمكنك استخراجه وكتابته في MDC إلى جانب معرّف التتبع:
finally. تُعيد حاويات Servlet استخدام الخيوط. إذا نسيت استدعاء MDC.remove()، سيتسرب معرّف الارتباط من الطلب A إلى الطلب B على الخيط ذاته — منتجًا سجلات خاطئة بصمت أصعب تصحيحًا من غياب الارتباط كليًا.
أضف %X{correlationId:-} إلى نمط سجلك ليظهر المعرّف على مستوى الأعمال إلى جانب معرّف Micrometer، مانحًا إياك عدستين تكمّل إحداهما الأخرى لفهم كل طلب.
نشر السياق إلى الخيوط غير المتزامنة
يُخزَّن MDC في ThreadLocal. عند إرسال عمل إلى ExecutorService أو استخدام @Async، يبدأ الخيط الجديد بـ MDC فارغ. يحلّ Micrometer Tracing هذا لنطاقاته عبر ContextSnapshot:
لاستخدام مجمع الخيوط اليدوي، غلّف Runnable بلقطة سياق لنسخ MDC عبر الخيوط:
اعتبار أمني: لا تثق بمعرّفات الارتباط الواردة بشكل أعمى
إذا قبلت قيمة X-Correlation-ID من عميل خارجي وسجّلتها حرفيًا، فأنت تفتح ثغرة حقن في السجل. قيمة خبيثة كـ abc\n14:32:00 WARN [attacker] Fake log line يمكنها تزوير مدخلات في مجرى سجلاتك مما يُفسد سجل المراجعة. عقّم الترويسة دائمًا قبل الكتابة إلى MDC:
الخلاصة
يُمثّل التسجيل الموزع ومعرّفات الارتباط أساس مراقبة الخدمات المصغّرة. أضف micrometer-tracing-bridge-brave إلى كل خدمة واسمح لـ Spring Boot بتهيئة معرّفات التتبع والنطاق في MDC تلقائيًا. استخدم الـ bean الخاص بـ WebClient.Builder للحصول على نشر تلقائي للترويسات. أضف نطاقات فرعية صريحة للعمليات التجارية المهمة باستخدام Tracer. أكمل تتبعات Micrometer بمرشّح OncePerRequestFilter مخصّص لمعرّفات الارتباط على مستوى الأعمال — وعقّم دائمًا قيم الترويسات الواردة ونظّف MDC في كتلة finally. بهذه الأجزاء مجتمعة، يفتح معرّف تتبع واحد القصة الكاملة لأي طلب عبر نظامك بأكمله.