Spring Boot Actuator
Actuator هو لوحة معلومات Spring Boot—يوفر حالة الصحة والمقاييس ومعلومات التكوين—ويمنح فرق العمليات "رؤية شاملة".
1. ما ستتعلمه
- نظرة عامة على نقاط نهاية Actuator:
/health//info//metrics//env//beans - تفعيل نقاط النهاية وسياسة الكشف:
management.endpoints.web.exposure.include - تخصيص HealthIndicator لمراقبة اتصال قاعدة البيانات مع الخدمات الخارجية
@ReadOperation/@WriteOperationنقاط نهاية مخصصة- تعزيز الأمان: التحكم في الوصول إلى نقاط النهاية وعزل الشبكة
2. قصة حقيقية لمهندس عمليات
(1) نقطة الألم: بيئة الإنتاج مثل الصندوق الأسود
Bob مسؤول عن عمليات وصيانة بيئة الإنتاج لـ OrderFlow، لكن التطبيق بالنسبة له صندوق أسود تمامًا: هل اتصالات قاعدة البيانات تعمل بشكل صحيح؟ كم الذاكرة المستخدمة؟ أي APIs تستجيب ببطء؟ في كل مرة تظهر مشكلة، يضطر لطلب من Alice إضافة سجلات أو إعادة تشغيل التطبيق لاستكشاف الأخطاء، مما يؤدي إلى متوسط وقت الاسترداد (MTTR) يتجاوز ساعة. Charlie طلب أن يُخفض MTTR إلى 10 دقائق.
(2) حل Actuator
Actuator جاهز للاستخدام فورًا ويقدم مجموعة واسعة من نقاط نهاية العمليات:
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
curl http://localhost:8080/actuator/health
# {"status":"UP","components":{"db":{"status":"UP"},"diskSpace":{"status":"UP"}}}
(3) العائد
بعد أن بدأ Bob باستخدام Actuator، راقب /health اتصال قاعدة البيانات، وتتبع /metrics أوقات استجابة API، وتحقق HealthIndicator المخصص من بوابة الدفع الخارجية، مما خفض MTTR من ساعة إلى 5 دقائق.
3. نظرة عامة على نقاط نهاية Actuator
(1) قائمة نقاط النهاية المدمجة
| نقطة النهاية | الوصف | الكشف الافتراضي |
|---|---|---|
/actuator/health |
حالة صحة التطبيق | ✅ نعم |
/actuator/info |
معلومات التطبيق | ✅ نعم |
/actuator/metrics |
قائمة المؤشرات | ❌ لا |
/actuator/metrics/{name} |
قيمة مقياس محدد | ❌ لا |
/actuator/env |
تكوين البيئة | ❌ لا |
/actuator/beans |
قائمة Bean | ❌ لا |
/actuator/loggers |
مستوى السجل | ❌ لا |
/actuator/threaddump |
تفريغ الخيوط | ❌ لا |
/actuator/heapdump |
تفريغ الكومة | ❌ لا |
/actuator/prometheus |
مقاييس بتنسيق Prometheus | ❌ لا |
(1) ▶ مثال:تفعيل تبعية Actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
الناتج:
// تم التنفيذ بنجاح
(2) ▶ مثال:تكوين كشف نقاط النهاية
management:
endpoints:
web:
exposure:
include: health,info,metrics,env,loggers
base-path: /actuator
endpoint:
health:
show-details: when-authorized
metrics:
enabled: true
info:
env:
enabled: true
الناتج:
تم تفعيل التكوين.
| سياسة الكشف | قيمة التكوين | الوصف |
|---|---|---|
| الصحة والمعلومات فقط | include: health,info |
الأكثر أمانًا، الافتراضي |
| كشف عند الطلب | include: health,info,metrics |
موصى به |
| عرض الكل | include: "*" |
بيئة التطوير فقط |
| استبعاد محدد | exclude: env,beans |
استبعاد من الكل |
4. شرح مفصل لنقطة نهاية Health
(1) قواعد تجميع حالة الصحة
graph TD
A["مُجمّع حالة<br/>الصحة"] --> B["DiskSpace<br/>UP"]
A --> C["DataSource<br/>UP"]
A --> D["PaymentGateway<br/>DOWN"]
A --> E["Redis<br/>UP"]
D --> F["الإجمالي: DOWN<br/>أي DOWN ← DOWN"]
| الحالة | المعنى | قواعد التجميع |
|---|---|---|
| UP | طبيعي | — |
| DOWN | استثناء | أي DOWN واحد ← الإجمالي DOWN |
| DEGRADED | متدهور | تدهور مكون غير حرج |
| OUT_OF_SERVICE | الخدمة غير متاحة | أي واحد ← الكل OUT_OF_SERVICE |
| UNKNOWN | غير معروف | الافتراضي |
(1) ▶ مثال:تخصيص HealthIndicator
@Component
public class PaymentGatewayHealthIndicator implements HealthIndicator {
private final RestTemplate restTemplate;
public PaymentGatewayHealthIndicator(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public Health health() {
try {
ResponseEntity<String> response = restTemplate.getForEntity(
"https://api.payment-gateway.com/ping", String.class);
if (response.getStatusCode().is2xxSuccessful()) {
return Health.up()
.withDetail("gateway", "reachable")
.withDetail("responseTime", response.getHeaders().getDate())
.build();
}
return Health.down()
.withDetail("gateway", "unhealthy")
.withDetail("statusCode", response.getStatusCode())
.build();
} catch (Exception e) {
return Health.down()
.withDetail("gateway", "unreachable")
.withDetail("error", e.getMessage())
.build();
}
}
}
الناتج:
// تم التنفيذ بنجاح
{
"status": "DOWN",
"components": {
"diskSpace": {"status": "UP", "details": {"total": 536870912000, "free": 268435456000}},
"db": {"status": "UP", "details": {"database": "MySQL", "validationQuery": "SELECT 1"}},
"paymentGateway": {"status": "DOWN", "details": {"gateway": "unreachable", "error": "Connection refused"}}
}
}
5. شرح مفصل لنقاط نهاية Metrics
(1) ▶ مثال:عرض مقاييس طلبات HTTP
# قائمة جميع المقاييس المتاحة
curl http://localhost:8080/actuator/metrics
# الحصول على مقياس محدد: طلبات خادم HTTP
curl http://localhost:8080/actuator/metrics/http.server.requests
# الحصول على مقياس مُفلتر
curl "http://localhost:8080/actuator/metrics/http.server.requests?tag=uri:/api/v1/orders&tag=status:200"
الناتج:
{"status":"ok","data":{}}
| المقاييس الشائعة | الوصف |
|---|---|
http.server.requests |
توزيع مدة طلبات HTTP |
jvm.memory.used |
استخدام ذاكرة JVM |
jvm.threads.live |
عدد الخيوط النشطة |
process.cpu.usage |
استخدام معالج العملية |
disk.total / disk.free |
مساحة القرص |
hikaricp.connections.active |
تجمع اتصالات قاعدة البيانات |
(2) ▶ مثال:مقاييس أعمال مخصصة
@Service
public class OrderMetrics {
private final Counter orderCreatedCounter;
private final Timer orderCreationTimer;
private final AtomicLong pendingOrders;
public OrderMetrics(MeterRegistry registry) {
this.orderCreatedCounter = Counter.builder("orderflow.orders.created")
.description("إجمالي الطلبات المنشأة")
.tag("service", "orderflow")
.register(registry);
this.orderCreationTimer = Timer.builder("orderflow.orders.creation.time")
.description("وقت إنشاء الطلب")
.register(registry);
this.pendingOrders = registry.gauge("orderflow.orders.pending",
new AtomicLong(0));
}
public void recordOrderCreated() {
orderCreatedCounter.increment();
pendingOrders.incrementAndGet();
}
public void recordOrderCompleted() {
pendingOrders.decrementAndGet();
}
public Timer getCreationTimer() {
return orderCreationTimer;
}
}
الناتج:
// تم التنفيذ بنجاح
6. نقاط نهاية مخصصة
(1) ▶ مثال:نقطة نهاية OrderStats مخصصة
@Endpoint(id = "orderstats")
@Component
public class OrderStatsEndpoint {
private final OrderRepository orderRepository;
public OrderStatsEndpoint(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
@ReadOperation
public Map<String, Object> orderStats() {
long total = orderRepository.count();
long pending = orderRepository.countByStatus("PENDING");
long completed = orderRepository.countByStatus("COMPLETED");
long cancelled = orderRepository.countByStatus("CANCELLED");
return Map.of(
"totalOrders", total,
"pendingOrders", pending,
"completedOrders", completed,
"cancelledOrders", cancelled,
"completionRate", total > 0
? String.format("%.2f%%", (double) completed / total * 100)
: "N/A"
);
}
@ReadOperation
public Map<String, Object> orderStatsByStatus(
@Selector String status) {
long count = orderRepository.countByStatus(status.toUpperCase());
return Map.of("status", status, "count", count);
}
}
الناتج:
// تم التنفيذ بنجاح
management:
endpoint:
orderstats:
enabled: true
endpoints:
web:
exposure:
include: health,info,orderstats
curl http://localhost:8080/actuator/orderstats
# {"totalOrders":1523,"pendingOrders":45,"completedOrders":1420,"cancelledOrders":58,"completionRate":"93.30%"}
curl http://localhost:8080/actuator/orderstats/PENDING
# {"status":"PENDING","count":45}
7. تعزيز الأمان
(1) سياسة أمان نقاط النهاية
| المستوى | السياسة | الوصف |
|---|---|---|
| طبقة الشبكة | منفذ إدارة مخصص | management.server.port=8081 |
| طبقة الشبكة | الربط بعنوان IP داخلي | management.server.address=127.0.0.1 |
| طبقة التطبيق | تحكم Spring Security | .requestMatchers("/actuator/**").hasRole("ADMIN") |
| طبقة نقطة النهاية | تعطيل نقاط النهاية الحساسة | management.endpoint.env.enabled=false |
(1) ▶ مثال:تكوين أمان بمستوى الإنتاج
# application-prod.yml
management:
server:
port: 8081 # منفذ إدارة منفصل
address: 127.0.0.1 # الربط بـ localhost فقط
endpoints:
web:
exposure:
include: health,prometheus,orderstats
base-path: /actuator
endpoint:
health:
show-details: when-authorized
env:
enabled: false
beans:
enabled: false
heapdump:
enabled: false
الناتج:
تم تحميل تكوين المراقبة
أهداف Prometheus: 3 نشطة
لوحة Grafana: جاهزة
| البيئة | سياسة الكشف | منفذ الإدارة |
|---|---|---|
| التطوير | include: "*" |
المنفذ 8080 |
| الاختبار | include: health,info,metrics,env |
نفس المنفذ 8080 |
| الإنتاج | include: health,prometheus |
منفذ مخصص 8081 + شبكة داخلية |
8. مثال شامل: تكوين كامل لـ OrderFlow Actuator
# application.yml
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus,orderstats
endpoint:
health:
show-details: when-authorized
orderstats:
enabled: true
metrics:
tags:
application: ${spring.application.name}
info:
env:
enabled: true
info:
app:
name: OrderFlow Service
version: @project.version@
description: خدمة إدارة طلبات التجارة الإلكترونية المصغرة
// PaymentGatewayHealthIndicator.java
@Component
public class PaymentGatewayHealthIndicator implements HealthIndicator {
private final RestTemplate restTemplate;
public PaymentGatewayHealthIndicator(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public Health health() {
try {
ResponseEntity<String> resp = restTemplate
.getForEntity("https://api.payment.com/ping", String.class);
return resp.getStatusCode().is2xxSuccessful()
? Health.up().withDetail("gateway", "reachable").build()
: Health.down().withDetail("statusCode", resp.getStatusCode()).build();
} catch (Exception e) {
return Health.down().withDetail("error", e.getMessage()).build();
}
}
}
// OrderStatsEndpoint.java
@Endpoint(id = "orderstats")
@Component
public class OrderStatsEndpoint {
private final OrderRepository orderRepository;
public OrderStatsEndpoint(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
@ReadOperation
public Map<String, Object> stats() {
return Map.of(
"total", orderRepository.count(),
"pending", orderRepository.countByStatus("PENDING"),
"completed", orderRepository.countByStatus("COMPLETED")
);
}
}
❓ أسئلة شائعة
/health لموازنات الحمل ومسبارات K8s؛ لا يكشف تفاصيل حساسة. /health مع التفاصيل مخصص لفرق العمليات ويتطلب صلاحيات ADMIN. استخدم show-details: when-authorized في بيئات الإنتاج.HealthAggregator أو استخدم bean الخاص بـ StatusAggregator. القاعدة الافتراضية هي: أي DOWN ← الإجمالي DOWN. يمكنك تخصيص الأولوية باستخدام statusOrder./actuator/env كلمات المرور؟password وsecret وkey وtoken (عرض •••••• بدلاً منها). لا يزال يُوصى بتعطيل هذه النقطة في بيئات الإنتاج.micrometer-registry-prometheus، واكشف نقطة النهاية prometheus، وأضف هدف جمع في تكوين Prometheus. سيتم تغطية ذلك بالتفصيل في درس لاحق (L23).📖 ملخص
- Actuator يوفر نقاط نهاية تشغيلية مثل الصحة والمقاييس والتكوين والخيوط؛ افتراضيًا يُكشف فقط health وinfo
- تخصيص HealthIndicator لمراقبة الاتصال بالخدمات الخارجية
- نقطة نهاية Metrics توفر مقاييس مدمجة لـ HTTP وJVM وتجمعات الاتصال والمزيد
- نقاط النهاية المخصصة تستخدم
@Endpoint+@ReadOperation/@WriteOperation - أمان الإنتاج: منفذ إدارة مخصص + ربط شبكة داخلية + كشف محدود + Spring Security
show-details: when-authorizedللتحكم في عرض تفاصيل الصحة
📝 تمارين
-
تمرين أساسي (صعوبة ⭐): أضف Actuator إلى OrderFlow، واكوّنه لكشف نقاط نهاية health وinfo وmetrics، وتحقق أن
/actuator/healthيُرجع حالة "UP". -
تمرين متقدم (صعوبة: ⭐⭐): نفّذ
PaymentGatewayHealthIndicatorوOrderStatsEndpointمخصصين، واكوّن منفذ إدارة منفصل لبيئة الإنتاج. -
تحدي (صعوبة: ⭐⭐⭐): أضف تبعية
micrometer-registry-prometheus، واكشف نقطة النهاية/actuator/prometheus، واكتب مقاييس أعمال مخصصة (عدد إنشاء الطلبات، وقت تقديم الطلب)، وفكر في اصطلاحات التسمية وتصميم الوسوم للمقاييس.



