فحوصات الصحة ونقاط نهاية المعلومات
حين تعمل خدمة في بيئة الإنتاج — خلف موازن تحميل، أو داخل عنقود Kubernetes، أو تحت إدارة منسّق حاويات — تحتاج البنية التحتية إلى طريقة موثوقة وقابلة للقراءة آليًا للسؤال: "هل هذا المثيل يعمل بصحة جيدة؟". يجيب Spring Boot Actuator على هذه الحاجة بنقطتَي نهاية جاهزتَين للاستخدام: /actuator/health و/actuator/info. يوضّح هذا الدرس بالضبط ما تكشفه، وكيف تتحكم فيما تُظهره، وكيف تكتب مؤشر صحة مخصصًا خاصًا بك حتى تمتلك المنصة رؤية كاملة على كل تبعية تعتمد عليها تطبيقاتك.
نقطة النهاية /actuator/health
أضف مُهيّئ Actuator إلى ملف pom.xml لتتوفر نقطة النهاية /actuator/health فورًا:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
يُعيد طلب GET بسيط إلى ذلك العنوان كائن JSON مُبسَّط:
{ "status": "UP" }
يمكن أن تكون الحالة UP أو DOWN أو OUT_OF_SERVICE أو UNKNOWN. وتكون الحالة الإجمالية هي الأسوأ بين جميع مؤشرات الصحة المسجّلة — فإذا كانت قاعدة بياناتك DOWN، يُفيد الطرف الكامل بـDOWN، وستُزيل موازنات التحميل التي تستطلع هذا العنوان المثيلَ من التوزيع.
لماذا الاستجابة المبسَّطة بشكل افتراضي؟ كشف التفاصيل الداخلية (مضيف قاعدة البيانات، عدد الاتصالات، مسارات الأقراص) لأي مُستدعٍ مجهول يُشكّل خطرًا أمنيًا. يُشحن Boot بإعداد افتراضي متحفّظ: الحالة الإجمالية فقط. لا تُوسّع الاستجابة إلا لحركة المرور الداخلية أو المصادَق عليها.
إظهار تفاصيل المكوّنات
لرؤية الحالة الفردية لكل مكوّن، اضبط إحدى هاتين الخاصيتين أو كلتيهما في application.properties:
# إظهار التفاصيل الكاملة للجميع (مناسب للخدمات الداخلية أو التطوير المحلي)
management.endpoint.health.show-details=always
# أو: إظهار التفاصيل للمستخدمين المصادَق عليهم فقط
management.endpoint.health.show-details=when-authorized
# إظهار أسماء المكوّنات حتى بدون التفاصيل الكاملة
management.endpoint.health.show-components=always
مع show-details=always تبدو استجابة نموذجية هكذا:
{
"status": "UP",
"components": {
"db": {
"status": "UP",
"details": { "database": "PostgreSQL", "validationQuery": "isValid()" }
},
"diskSpace": {
"status": "UP",
"details": { "total": 499963174912, "free": 341024587776, "threshold": 10485760 }
},
"ping": { "status": "UP" }
}
}
يُهيّئ Spring Boot مؤشر صحة تلقائيًا لكل تقنية يكتشفها: DataSource، وRedis، وRabbitMQ، وKafka، وMongoDB، وElasticsearch، والمزيد. تحصل على هذه التغطية مجانًا؛ ولا تحتاج إلى كتابة مؤشرات مخصصة إلا للتبعيات التي لا يعرفها Boot.
مسابر الاستمرارية والجاهزية
يُميّز Kubernetes والمنسّقون الآخرون بين مفهومَين للصحة. تسأل الاستمرارية (Liveness): "هل يجب إعادة تشغيل هذه الحاوية؟" (هل JVM عالقة في توقف تام؟). وتسأل الجاهزية (Readiness): "هل يجب أن يتلقى هذا المثيل حركة مرور؟" (هل التطبيق بدأ بالكامل وتبعياته قابلة للوصول؟). يعرض Boot كليهما كمسارات فرعية من /actuator/health:
# application.properties
management.health.livenessstate.enabled=true
management.health.readinessstate.enabled=true
أو يمكنك تمكينهما معًا بـ:
management.endpoint.health.probes.enabled=true
يعرض Boot بعدها /actuator/health/liveness و/actuator/health/readiness بشكل منفصل. وجّه مسبار الاستمرارية في Kubernetes إلى العنوان الأول، ومسبار الجاهزية إلى الثاني.
النمط الإنتاجي في Kubernetes: لا توجّه مسبار الاستمرارية أبدًا إلى عنوان URL يفحص التبعيات الخارجية. انقطاع مؤقت في قاعدة البيانات يجب ألا يُسبّب موجة من إعادات تشغيل الـ pods. ضع فحوصات التبعيات الخارجية في مسبار الجاهزية فقط.
كتابة مؤشر صحة مخصص
تخيّل أن تطبيقك يستدعي بوابة دفع خارجية. لا يوجد مؤشر مدمج لها في Boot. نفّذ واجهة HealthIndicator وسجّل حبّة Spring:
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class PaymentGatewayHealthIndicator implements HealthIndicator {
private final PaymentGatewayClient client;
public PaymentGatewayHealthIndicator(PaymentGatewayClient client) {
this.client = client;
}
@Override
public Health health() {
try {
boolean reachable = client.ping(); // فحص خفيف الوزن
if (reachable) {
return Health.up()
.withDetail("url", client.getBaseUrl())
.withDetail("latencyMs", client.lastPingLatency())
.build();
}
return Health.down()
.withDetail("reason", "ping returned false")
.build();
} catch (Exception ex) {
return Health.down(ex)
.withDetail("url", client.getBaseUrl())
.build();
}
}
}
يُسمّي Boot المكوّن استنادًا إلى اسم الحبّة، مُزيلًا لاحقة HealthIndicator. تظهر الحبّة أعلاه في استجابة الصحة باسم "paymentGateway". لديك تحكم كامل في خريطة details ويمكنك تمرير أي قيمة قابلة للتحويل إلى JSON.
احرص على أن تكون فحوصات الصحة سريعة وخفيفة الوزن. تُستطلَع نقطة النهاية /actuator/health باستمرار من المنسّقين وموازنات التحميل — أحيانًا كل بضع ثوانٍ. فحص الصحة الذي يُشغّل استعلامًا معقدًا أو ينتظر على اتصال شبكي بطيء سيُدهور الأداء ويجعل الحالة الإجمالية غير موثوقة. استخدم ping رخيصًا، أو SELECT 1، أو استدعاء API خفيف لفحص الحالة.
مؤشرات الصحة التفاعلية
إذا كان تطبيقك يستخدم Spring WebFlux (المكدّس التفاعلي)، نفّذ ReactiveHealthIndicator بدلًا من ذلك حتى لا تُعيق حلقة الأحداث:
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component
public class ExternalCacheHealthIndicator implements ReactiveHealthIndicator {
private final ReactiveCacheClient cacheClient;
public ExternalCacheHealthIndicator(ReactiveCacheClient cacheClient) {
this.cacheClient = cacheClient;
}
@Override
public Mono<Health> health() {
return cacheClient.ping()
.map(ok -> Health.up().withDetail("cache", "reachable").build())
.onErrorResume(ex -> Mono.just(Health.down(ex).build()));
}
}
نقطة النهاية /actuator/info
تعرض /actuator/info بيانات وصفية ثابتة عن الأداة المُنشورة — الإصدار، وطابع زمن البناء، وتجزئة Git commit، والخصائص المخصصة. إنها لا تُقدَّر بثمن أثناء الحوادث: نظرة واحدة تُخبرك بالضبط أي بناء يعمل على كل عقدة دون تسجيل دخول إلى أي خادم.
أولًا، اكشف نقطة النهاية (هي مُعطَّلة افتراضيًا منذ Boot 2.6):
# application.properties
management.endpoints.web.exposure.include=health,info
management.info.env.enabled=true
ثم أضف أزواج المفتاح/القيمة تحت فضاء الأسماء info.*:
info.app.name=Order Service
info.app.version=2.4.1
info.app.team=platform
info.contact.email=platform@example.com
تعكس الاستجابة هيكل هذه المفاتيح:
{
"app": {
"name": "Order Service",
"version": "2.4.1",
"team": "platform"
},
"contact": { "email": "platform@example.com" }
}
معلومات البناء و Git عبر إضافات Maven/Gradle
تأتي القوة الحقيقية لـ/actuator/info من دمجها مع إضافات البناء. يمكن لإضافة Maven الخاصة بـ Spring Boot توليد ملف build-info.properties وقت البناء، وتستطيع إضافة git-commit-id تضمين تجزئة Git SHA بدقة:
<!-- pom.xml — داخل <build><plugins> -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals><goal>build-info</goal></goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
<version>9.0.0</version>
<executions>
<execution>
<goals><goal>revision</goal></goals>
</execution>
</executions>
</plugin>
فعّل المساهمين في application.properties:
management.info.build.enabled=true
management.info.git.enabled=true
management.info.git.mode=full
الآن تتضمّن /actuator/info وقت البناء، وإصدار القطعة من POM الخاص بك، وفرع Git، وتجزئة commit، ووقت commit، وما إذا كان شجرة العمل غير نظيفة وقت البناء. قد تبدو الاستجابة هكذا:
{
"build": {
"artifact": "order-service",
"version": "2.4.1",
"time": "2024-11-15T09:23:41.000Z",
"group": "com.example"
},
"git": {
"branch": "main",
"commit": {
"id": "a3f8c12",
"time": "2024-11-15T09:15:00.000Z",
"message": { "short": "fix: handle null order ID" }
},
"dirty": false
}
}
InfoContributor مخصص
للمعلومات الديناميكية — كعدد أعلام الميزات النشطة أو ملخّص الإعداد في وقت التشغيل — نفّذ InfoContributor:
import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;
@Component
public class FeatureFlagInfoContributor implements InfoContributor {
private final FeatureFlagService flags;
public FeatureFlagInfoContributor(FeatureFlagService flags) {
this.flags = flags;
}
@Override
public void contribute(Info.Builder builder) {
builder.withDetail("featureFlags", flags.getActiveFlags());
}
}
الخلاصة
تمنح /actuator/health بنيتك التحتية إشارة موثوقة عن الاستمرارية والجاهزية. تغطّي المؤشرات المُهيَّأة تلقائيًا التكاملات القياسية؛ أما الحبوب المخصصة من نوع HealthIndicator فتتكفل بكل ما عداها. احرص على أن تكون الفحوصات رخيصة ومحدّدة. تضمّن /actuator/info بيانات البناء وGit في القطعة الجاري تشغيلها، محوّلةً كل عملية نشر إلى أداة تصف نفسها بنفسها. يشكّل هذان الطرفان معًا العقد الأساسي للمراقبة بين تطبيقك والمنصة التي يعمل عليها. الدرس التالي يوسّع الصورة بمقاييس Micrometer.