404 Not Found

404 Not Found


nginx

Spring Boot Actuator

Actuator هو لوحة معلومات Spring Boot—يوفر حالة الصحة والمقاييس ومعلومات التكوين—ويمنح فرق العمليات "رؤية شاملة".

1. ما ستتعلمه


2. قصة حقيقية لمهندس عمليات

(1) نقطة الألم: بيئة الإنتاج مثل الصندوق الأسود

Bob مسؤول عن عمليات وصيانة بيئة الإنتاج لـ OrderFlow، لكن التطبيق بالنسبة له صندوق أسود تمامًا: هل اتصالات قاعدة البيانات تعمل بشكل صحيح؟ كم الذاكرة المستخدمة؟ أي APIs تستجيب ببطء؟ في كل مرة تظهر مشكلة، يضطر لطلب من Alice إضافة سجلات أو إعادة تشغيل التطبيق لاستكشاف الأخطاء، مما يؤدي إلى متوسط وقت الاسترداد (MTTR) يتجاوز ساعة. Charlie طلب أن يُخفض MTTR إلى 10 دقائق.

(2) حل Actuator

Actuator جاهز للاستخدام فورًا ويقدم مجموعة واسعة من نقاط نهاية العمليات:

YAML
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
BASH
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

XML
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

الناتج:

TEXT
// تم التنفيذ بنجاح

(2) ▶ مثال:تكوين كشف نقاط النهاية

YAML
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

الناتج:

TEXT
تم تفعيل التكوين.
سياسة الكشف قيمة التكوين الوصف
الصحة والمعلومات فقط include: health,info الأكثر أمانًا، الافتراضي
كشف عند الطلب include: health,info,metrics موصى به
عرض الكل include: "*" بيئة التطوير فقط
استبعاد محدد exclude: env,beans استبعاد من الكل

4. شرح مفصل لنقطة نهاية Health

(1) قواعد تجميع حالة الصحة

100%
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

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> 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();
        }
    }
}

الناتج:

TEXT
// تم التنفيذ بنجاح
💻 الناتج:

JSON
{
  "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

BASH
# قائمة جميع المقاييس المتاحة
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"

الناتج:

TEXT
{"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) ▶ مثال:مقاييس أعمال مخصصة

JAVA
@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;
    }
}

الناتج:

TEXT
// تم التنفيذ بنجاح

6. نقاط نهاية مخصصة

(1) ▶ مثال:نقطة نهاية OrderStats مخصصة

JAVA
@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);
    }
}

الناتج:

TEXT
// تم التنفيذ بنجاح
YAML
management:
  endpoint:
    orderstats:
      enabled: true
  endpoints:
    web:
      exposure:
        include: health,info,orderstats
💻 الناتج:

BASH
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) ▶ مثال:تكوين أمان بمستوى الإنتاج

YAML
# 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

الناتج:

TEXT
تم تحميل تكوين المراقبة
أهداف Prometheus: 3 نشطة
لوحة Grafana: جاهزة
البيئة سياسة الكشف منفذ الإدارة
التطوير include: "*" المنفذ 8080
الاختبار include: health,info,metrics,env نفس المنفذ 8080
الإنتاج include: health,prometheus منفذ مخصص 8081 + شبكة داخلية

8. مثال شامل: تكوين كامل لـ OrderFlow Actuator

YAML
# 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: خدمة إدارة طلبات التجارة الإلكترونية المصغرة
JAVA
// 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")
        );
    }
}

❓ أسئلة شائعة

س هل تؤثر نقاط نهاية Actuator على الأداء؟
ج عمليات القراءة (health, metrics) لها عبء ضئيل. عمليات heapdump وthreaddump توقف التطبيق وهي معطلة افتراضيًا في بيئات الإنتاج. الفاصل الزمني الموصى به لجلب بيانات Prometheus هو 15-30 ثانية.
س من يجب أن يستخدم نقطة نهاية فحص الصحة؟
ج /health لموازنات الحمل ومسبارات K8s؛ لا يكشف تفاصيل حساسة. /health مع التفاصيل مخصص لفرق العمليات ويتطلب صلاحيات ADMIN. استخدم show-details: when-authorized في بيئات الإنتاج.
س كيف أخصص قواعد تجميع حالة الصحة؟
ج نفّذ HealthAggregator أو استخدم bean الخاص بـ StatusAggregator. القاعدة الافتراضية هي: أي DOWN ← الإجمالي DOWN. يمكنك تخصيص الأولوية باستخدام statusOrder.
س هل يكشف /actuator/env كلمات المرور؟
ج يعرض قيم التكوين، لكن افتراضيًا في Spring Boot 3.x يتم إخفاء أزواج المفاتيح التي تحتوي على password وsecret وkey وtoken (عرض •••••• بدلاً منها). لا يزال يُوصى بتعطيل هذه النقطة في بيئات الإنتاج.
س ما فوائد فصل منافذ الإدارة عن منافذ التطبيق؟
ج 1) منافذ الإدارة مرتبطة فقط بالشبكة الداخلية ولا تُعرض للإنترنت العام؛ 2) حركة التطبيق وحركة الإدارة معزولتان ولا تتداخلان؛ 3) يمكن تكوين سياسات أمان مختلفة لمنافذ الإدارة.
س كيف أدمج مقاييس Actuator مع Prometheus؟
ج أضف تبعية micrometer-registry-prometheus، واكشف نقطة النهاية prometheus، وأضف هدف جمع في تكوين Prometheus. سيتم تغطية ذلك بالتفصيل في درس لاحق (L23).

📖 ملخص


📝 تمارين

  1. تمرين أساسي (صعوبة ⭐): أضف Actuator إلى OrderFlow، واكوّنه لكشف نقاط نهاية health وinfo وmetrics، وتحقق أن /actuator/health يُرجع حالة "UP".

  2. تمرين متقدم (صعوبة: ⭐⭐): نفّذ PaymentGatewayHealthIndicator وOrderStatsEndpoint مخصصين، واكوّن منفذ إدارة منفصل لبيئة الإنتاج.

  3. تحدي (صعوبة: ⭐⭐⭐): أضف تبعية micrometer-registry-prometheus، واكشف نقطة النهاية /actuator/prometheus، واكتب مقاييس أعمال مخصصة (عدد إنشاء الطلبات، وقت تقديم الطلب)، وفكر في اصطلاحات التسمية وتصميم الوسوم للمقاييس.

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%