Spring AI · Metrikalar və sorğuların izlənməsi · Dərs 1

Spring Boot Actuator ilə müşahidə

Spring Boot Actuator və Micrometer ilə Spring AI tətbiqinin metrikalarını müşahidə et və sorğuların keçdiyi mərhələləri izlə.

Spring Boot Actuator ilə müşahidə

1. Study Coach haqqında üç ayrı sual

Study Coach sorğunu qəbul edə, modelə müraciət edə və faydalı cavab qaytara bilər. Bunlar ayrı-ayrı iddialardır. Java prosesinin işləməsi HTTP serverin trafik qəbul etdiyini, HTTP serverin sağlam olması isə son model cavabının düzgün olduğunu sübut etmir.

SiqnalCavab verdiyi sualSübut etmədiyi məqam
HealthBu instansiya işləyirmi və ya trafik qəbul etməyə hazırdırmı?Cavabın keyfiyyəti və ayrıca yoxlanılmırsa, provayderin əlçatanlığı
MetrikalarNeçə əməliyyat olub, nə qədər vaxt aparıb, bildirilən istifadə nə qədər artıb?Bir sorğunun dəqiq icra yolu
İzlərHansı müşahidə olunan əməliyyatlar eyni seçilmiş sorğuya aiddir?Bütün sorğuların tam qeydi

Bu modulda Actuator lokal sağlamlıq məlumatını təqdim edir, Micrometer ümumi ölçmələri qeyd edir, tracing handler isə müşahidələri span-larla əlaqələndirir. Üç dərsdə eyni Java 21 layihəsindən istifadə edirik. Modeli loopback ünvanında işləyən HTTP stub əvəz edir. API açarı, ödənişli çağırış və xarici telemetriya toplayıcısı lazım deyil.

2. Lokal layihəni yaradın

Boş observability-lab qovluğu yaradın. Hər bloku üzərində göstərilən yolda saxlayın, lazım olan alt qovluqları yaradın. POM Spring Boot 3.5.9 və Spring AI 1.1.8 versiyalarını sabitləyir. Boot Micrometer 1.15.7, Micrometer Tracing 1.5.7 və OpenTelemetry 1.49.0 versiyalarını idarə edir. Burada bu versiyalar yoxlanılıb; daha yeni buraxılışların hamısının eyni davranacağı iddia edilmir.

Model starter-i olmadan birbaşa spring-ai-openai istifadə edirik. Sonra modeli açıq şəkildə yaradıb ona ObservationRegistry verəcəyik. Actuator Boot-un registry və metrika infrastrukturunu təmin edir. Tracing asılılıqları test əhatəsindədir, çünki son dərs məlumatı yalnız yaddaşa ixrac edir.

pom.xml

xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.5.9</version><relativePath/></parent>
  <groupId>academy.study</groupId><artifactId>observability-lab</artifactId><version>1.0.0</version>
  <properties><java.version>21</java.version><spring-ai.version>1.1.8</spring-ai.version></properties>
  <dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><version>${spring-ai.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
  <dependencies>
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
    <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-openai</artifactId></dependency>
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
    <dependency><groupId>io.micrometer</groupId><artifactId>micrometer-tracing-bridge-otel</artifactId><scope>test</scope></dependency>
    <dependency><groupId>io.opentelemetry</groupId><artifactId>opentelemetry-sdk-testing</artifactId><scope>test</scope></dependency>
  </dependencies>
  <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

src/main/java/academy/study/observability/StudyApplication.java

Java
package academy.study.observability;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class StudyApplication {
    public static void main(String[] args) {
        SpringApplication.run(StudyApplication.class, args);
    }
}

3. İdarəetmə girişini lokal və məhdud saxlayın

0 portu əməliyyat sistemindən boş port seçməyi istəyir. Tətbiq və idarəetmə serveri ayrı loopback portlarında işləyir. Standart halda yalnız health açıqdır. Növbəti metrikalar dərsində ayrıca seçilən lokal profil əlavə edəcəyik.

src/main/resources/application.yml

yaml
server:
  address: 127.0.0.1
  port: 0
management:
  server:
    address: 127.0.0.1
    port: 0
  endpoints:
    web:
      exposure:
        include: health
  endpoint:
    health:
      show-details: never
      show-components: never
      probes:
        enabled: true
        add-additional-paths: true
  tracing:
    enabled: false
logging:
  level:
    org.springframework.ai.openai.OpenAiChatModel: "OFF"

Endpoint-i açmaq onu əlçatan edir, müraciət edənin kimliyini yoxlamır. Bu laboratoriyada Spring Security asılılığı yoxdur. Ona görə bu lokal portlara çatan istənilən proses açıq endpoint-ləri oxuya bilər. İstehsal mühitində autentifikasiya, səlahiyyət yoxlaması və şəbəkə məhdudiyyətləri ayrıca qurulmalıdır. Ünvanı ictimai interfeysə dəyişib idarəetmə portunun özünü qoruma vasitəsi saymayın.

show-details: never və show-components: never sağlamlıq komponentlərinin təfərrüatlarını gizlədir. Cavabda yenə liveness və readiness qruplarının adları görünə bilər. /livez və /readyz tətbiq portuna əlavə olunur. Bu, idarəetmə serverinin cavab verdiyi, tətbiq serverinin isə trafikə xidmət edə bilmədiyi vəziyyəti gözdən qaçırmamağa kömək edir.

Laboratoriyada tracing avtomatik konfiqurasiyası söndürülüb. Son dərs test üçün ayrıca registry və tracer yaradır. Konkret adapterin logger-i də söndürülüb, çünki Spring AI 1.1.8 boş completion haqqında xəbərdarlıqda prompt-u yaza bilər. Bu davranış müşahidələrdə məzmunun istəyə bağlı loglanmasından ayrıdır.

4. Yoxlamadan əvvəl sağlamlığın mənasını seçin

Liveness bu instansiyanı yenidən başlatmağın kömək edib-etməyəcəyini soruşur. Model provayderinin müvəqqəti nasazlığı bütün Study Coach instansiyalarının liveness yoxlamasını uğursuz edib onları birlikdə yenidən başlatmamalıdır. Uzaq model çağırışını liveness yoxlamasına əlavə etməyin.

Readiness instansiyanın yeni trafik qəbul edib-etməməli olduğunu soruşur. Boot-un readiness qrupu tətbiqin əlçatanlıq vəziyyətindən istifadə edir və bütün xarici asılılıqları avtomatik əlavə etmir. Provayder işləməsə də Study Coach saxlanmış dərsləri göstərə bilirsə, bütün instansiyanı trafikdən çıxarmaq yanlış qərar ola bilər. Ortaq provayderi düşünmədən bu yoxlamaya əlavə etsəniz, onun nasazlığı bütün instansiyaları trafikdən çıxara bilər.

Nümunə tətbiqin readiness vəziyyətini açıq şəkildə dəyişir. Provayderə müraciət etmir. Buna görə UP model giriş məlumatlarının işlədiyini və ya yaradılan cavabların kursun keyfiyyət tələblərinə uyğun olduğunu göstərmir. Ödənişli model qiymətləndirməsini tez-tez işləyən sağlamlıq yoxlamalarından ayrı saxlayın.

5. Həqiqi HTTP davranışını yoxlayın

Bu testi saxlayın. Test təsadüfi lokal portlarda həqiqi daxili HTTP serverləri başladır, endpoint girişinin məhdudluğunu yoxlayır və trafikdən imtinanın liveness-i pozmadan readiness-i dəyişdirdiyini göstərir. finally bloku əlçatanlığı bərpa edir ki, növbəti test uğursuz vəziyyəti miras almasın.

src/test/java/academy/study/observability/ActuatorTest.java

Java
package academy.study.observability;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.web.server.LocalManagementPort;
import org.springframework.boot.availability.AvailabilityChangeEvent;
import org.springframework.boot.availability.ReadinessState;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.context.ConfigurableApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class ActuatorTest {
    @LocalServerPort int appPort;
    @LocalManagementPort int managementPort;
    @Autowired TestRestTemplate http;
    @Autowired ConfigurableApplicationContext context;

    @Test void healthHasNoComponentDetails() {
        var response = http.getForEntity(url(managementPort, "/actuator/health"), String.class);
        assertThat(response.getStatusCode().value()).isEqualTo(200);
        assertThat(response.getBody()).contains("\"status\":\"UP\"").doesNotContain("components", "details");
        assertThat(managementPort).isNotEqualTo(appPort);
    }

    @Test void diagnosticEndpointsAreNotExposed() {
        for (String path : new String[]{"/actuator/metrics", "/actuator/env"}) {
            assertThat(http.getForEntity(url(managementPort, path), String.class)
                    .getStatusCode().value()).isEqualTo(404);
        }
    }

    @Test void refusingTrafficDoesNotFailLiveness() {
        AvailabilityChangeEvent.publish(context, ReadinessState.REFUSING_TRAFFIC);
        try {
            assertThat(http.getForEntity(url(appPort, "/readyz"), String.class)
                    .getStatusCode().value()).isEqualTo(503);
            assertThat(http.getForEntity(url(appPort, "/livez"), String.class)
                    .getStatusCode().value()).isEqualTo(200);
        } finally {
            AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
        }
        assertThat(http.getForEntity(url(appPort, "/readyz"), String.class)
                .getStatusCode().value()).isEqualTo(200);
    }

    static String url(int port, String path) {
        return "http://127.0.0.1:" + port + path;
    }
}

Layihə qovluğunda Java 21 və Maven 3.9.x ilə işlədin:

Terminal
mvn -B -Dtest=ActuatorTest test

Üç test keçməlidir. İlk icrada asılılıqlar endirilə bilər. Onlar keşdə olduqdan sonra eyni əmri mvn -o ilə işlədərək Maven asılılıqlarını oflayn həll etmək olar. Portlar, başlanğıc logları və vaxtlar dəyişir; yoxlanılan şərtlər sabit qalır.

6. Nəticəni əməliyyat qərarına çevirin

/readyz 503, /livez isə 200 qaytarırsa, instansiya işləyir, amma yeni trafik qəbul etməməlidir. Readiness qərarının səbəbini araşdırın. Yenidən başlatmaq avtomatik olaraq düzgün həll deyil. Hər ikisi 200 qaytardığı halda tələbələr cavabların gecikdiyini bildirirsə, health artıq kifayət etmir. Növbəti dərs əməliyyat müddətini və uğursuzluqları ölçür.

Health indicator əlavə etməzdən əvvəl onun nəyi yoxladığını, vaxt həddini, ödənişli çağırış edib-etmədiyini və uğursuzluq zamanı yük paylayıcısının və ya orkestratorun nə edəcəyini yazın. Cavab təfərrüatlarına şəxsi məzmun və giriş məlumatları əlavə etməyin. İdarəetmə portu ilə yanaşı, həqiqi tətbiq portunu və yerləşdirmə marşrutlarını da yoxlayın.

Bu laboratoriya Boot-un lokal davranışını yoxlayır. Kubernetes yerləşdirməsi, istehsal mühitinin giriş siyasəti, həqiqi provayder və yaradılan cavabın keyfiyyəti yoxlanılmır.

Mənbələr: