CodeGym /Kursy /Spring Boot /health i info w Actuatorze

health i info w Actuatorze

Spring Boot
Poziom 22, Lekcja 1
Dostępny

1. health i info jako minimalny zestaw

Jeśli po raz pierwszy otwierasz Actuator, łatwo wpaść w dwa skrajne stany: albo „wow, otworzę wszystko, niech będzie", albo „oj, to chyba dla DevOps, za wcześnie dla mnie". Żeby nie wpaść w obie pułapki, warto zacząć od dwóch endpointów, które przynoszą pożytek nawet małemu serwisowi: health i info. Pierwszy odpowiada na bardzo krótkie pytanie „czy serwis żyje", drugi – „czym jest ten serwis". Razem tworzą minimalną „wizytówkę operacyjną" aplikacji, wygodną do sprawdzania zarówno oczami, jak i automatyką.

Wyobraź sobie, że Twój serwis to kawiarnia. health to tabliczka na drzwiach „Otwarte/Zamknięte", a info to „jak nazywa się kawiarnia i co w niej sprzedajecie". Ani menu, ani księgowości, ani tajnego przepisu na sos nie wywieszamy na drzwiach. Ale „otwarte/zamknięte" i „jak was nazywacie" – jak najbardziej.

Żeby utrwalić różnicę, oto mała tabelka (można ją trzymać w głowie za każdym razem, gdy ręka ciągnie się „no, dajmy do info absolutnie wszystko"):

Endpoint Główne pytanie Dla kogo Jaka powinna być odpowiedź
health „Czy serwis jest w porządku?" przede wszystkim dla maszyn (checks), ale przydatne i człowiekowi krótka, stabilna, bezpieczna
info „Czym jest ten serwis?" przede wszystkim dla człowieka (rozumienie), czasem dla toolingu nieduża, neutralna, bez sekretów

I jeszcze jeden ważny niuans, który często psuje nervowy system nowicjusza: endpoint może istnieć, ale być niedostępny po HTTP przez politykę exposure. Czyli „jest w aplikacji", ale „w przeglądarce 404". To nie mistyka i nie „Actuator nie działa", to po prostu osobne ustawienie publikowania. Na razie skupiamy się na sensie i zawartości health/info.

2. /actuator/health: sprawdzanie serwisu

Gdy mówimy „sprawdzić serwis", początkujący deweloper robi to często po staremu: otwiera przeglądarkę, stuka w GET /api/catalog/courses i jeśli przyszedł JSON – „no to żyje". To oczywiście działa, ale słabo się skaluje: biznesowy endpoint może padać z powodów niezwiązanych ze zdrowiem aplikacji, poza tym może być wyłączony, wymagać parametrów lub zmieniać kontrakt. health to specjalny punkt, który ma jedno zadanie: uczciwie i krótko powiedzieć, czy wszystko OK z punktu widzenia „żywotności" serwisu.

W najprostszej formie health wygląda maksymalnie skromnie: zwraca JSON ze statusem. W prostym przypadku zobaczysz:

{
  "status": "UP"
}

I to „UP" jest już przydatniejsze, niż się wydaje. To nie „kontroler zwrócił odpowiedź", to właśnie „Actuator uważa aplikację za żywą". Czyli zaczynasz oddzielać „serwis podniósł się jako platforma" od „nasza logika domenowa zadziałała".

Nieco bardziej przyziemnie dla dewelopera pomaga to w dwóch typowych sytuacjach. Pierwsza – zmieniłeś konfig, serwis wystartował, port słucha, ale masz wątpliwości „czy on naprawdę jest OK, czy tylko widzę Tomcata?". Druga – serwis nie padł całkowicie, ale gdzieś „pod maską" coś jest nie tak, i chcesz szybki sygnał, zanim zaczniesz wchodzić w logi i debugowanie.

Jeśli chcesz sprawdzić ręcznie, zazwyczaj wygląda to tak:

# -s (silent) usuwa zbędny szum, żeby w wyjściu były tylko dane
# jq . ładnie formatuje JSON, żeby oczami łatwiej sprawdzić strukturę
curl -s http://localhost:8080/actuator/health | jq .
# {
#   "status": "UP"
# }

Tak, używamy curl i jq, bo to najszybsza droga do upewnienia się, że endpoint zwraca to, czego oczekujesz. Można i w przeglądarce – ale w terminalu szybciej zaczynasz myśleć „endpoint = dane", a nie „endpoint = strona".

3. Szczegóły health: show-details

Po pierwszym „status: UP" u nowicjusza często pojawia się naturalne życzenie: „A można, żeby health wyjaśniał absolutnie wszystko? Niech pisze, jakie beany wstały, jakie properties wygrały i najlepiej jeszcze listę kursów w katalogu". To życzenie jest zrozumiałe, ale niebezpieczne. health to drzwi, a nie wycieczka po serwerowni. Jeśli zaczniesz zbyt wcześnie ujawniać szczegóły, ryzykujesz, że diagnostyka stanie się albo hałaśliwa, albo wrażliwa na dane.

Dlatego rozsądny start – trzymać health krótkim, a szczegóły włączać tylko gdy jest to naprawdę potrzebne i tylko tam, gdzie to stosowne. W Actuatorze steruje tym ustawienie show-details. W bezpiecznym baseline (szczególnie gdy endpoint może potencjalnie być dostępny nie tylko Tobie) ustawiamy never.

Przykład konfiguracji w src/main/resources/application.yaml:

management:
  endpoint:
    health:
      # Bazowe ustawienie dla „bezpiecznego" zdrowia: tylko status bez szczegółów
      show-details: never

W tym wariancie health pozostaje zwięzły. Wygodnie to nawet lokalnie: najpierw przyzwyczajasz się postrzegać health jako „sygnalizator", a potem – jako „raport".

Czasem w profilu lokalnym chce się widzieć więcej. To normalne, ale rób to świadomie i wiąż z profilami, żeby przypadkowo nie zaciągnąć „gadatliwości" do bardziej rygorystycznego środowiska. Na przykład w src/main/resources/application-local.yaml można zrobić tak:

management:
  endpoint:
    health:
      # Lokalnie możemy być bardziej rozmowni, żeby szybciej diagnozować problemy
      show-details: always

W tym trybie odpowiedź staje się dłuższa i może zawierać „komponenty" (części sprawdzenia) i ich stan. Mniej więcej tak (forma może się trochę różnić, ale sens jest jeden):

{
  "status": "UP",
  "components": {
    "diskSpace": {
      "status": "UP"
    },
    "ping": {
      "status": "UP"
    }
  }
}

Zwróć uwagę na psychologicznie ważny efekt: zaczynasz widzieć, że „zdrowie" to nie magiczne UP/DOWN, lecz agregacja kilku sprawdzeń. Ale jeszcze raz – na starcie kursu lepiej trzymać to w lokalnej piaskownicy, a nie pokazywać wszystkim wszystko.

4. /actuator/info: wizytówka aplikacji

Jeśli health to „czy żyje", to info to „kim jesteś". Najczęstszy błąd z info wygląda tak: deweloper postrzega go jako „no to informacje, więc dajmy tam konfig, zmienne środowiskowe, tokeny, URL-e i w ogóle wszystko, co nie jest przykręcone". Efektem jest to, że info zamienia się w „publiczny README + przypadkowy wyciek wnętrzności". A potem ktoś się dziwi, dlaczego bezpieczeństwo to ból.

Właściwy model dla info jest taki: to krótki JSON, który pomaga człowiekowi (lub systemowi obserwacji) szybko zrozumieć, jaki serwis jest uruchomiony, jakiej jest wersji i w jakim trybie działa. Czyli neutralne, stabilne informacje.

Tu łatwo pomylić dwie różne rzeczy: co info powinno zawierać a czy jest on teraz dostępny po HTTP. Nawet jeśli wizytówka jest poprawnie zebrana, po URL-u można zobaczyć 404, jeśli endpoint nie jest jeszcze opublikowany na zewnątrz. Dlatego poniżej patrzymy właśnie na payload info i na to, jakie dane tam stosownie umieszczać.

W catalog-service dobrymi kandydatami do info są zazwyczaj nazwa aplikacji, jej wersja (nawet jeśli na razie piszesz ją ręcznie jako string), krótki opis i jakieś bardzo neutralne tryby, np. „read-only catalog". Idea jest prosta: info powinno być przydatne, nawet gdy otworzysz go po miesiącu i już zapomnisz, co dokładnie kręciłeś w konfigu.

W Spring Boot info jest zbierane z „kontrybutorów" (contributors). Na bazowym poziomie kursu ważne jest zrozumienie jednej konkretnej rzeczy: możesz umieścić dane pod kluczami info.* w konfiguracji, i one (przy włączonym env-kontrybutorze) trafią do odpowiedzi info jako ustrukturyzowany JSON.

Włącza się to tak:

management:
  info:
    env:
      # Zezwalamy na pobieranie danych z bloku info.* i oddawanie ich w /actuator/info
      enabled: true

A same dane można podać tak:

info:
  app:
    # Nazwa serwisu (to, co chcesz widzieć w „wizytówce")
    name: "catalog-service"
    # Krótki neutralny opis – bez sekretów i bez danych domenowych
    description: "Read-only catalog of courses"
    # Wersja przydatna do diagnostyki: „która kompilacja teraz działa?"
    version: "1.0.0"

Jeśli wszystko jest podłączone jak trzeba, odpowiedź /actuator/info będzie wyglądać mniej więcej tak:

{
  "app": {
    "name": "catalog-service",
    "description": "Read-only catalog of courses",
    "version": "1.0.0"
  }
}

To jak plakietka na konferencji: imię, rola, ewentualnie firma. Nie Twoja korespondencja na Slacku i hasło do Wi-Fi.

5. Konfiguracja health i info w catalog-service

Teraz najlepsze: nie tylko „dowiedzieliśmy się o endpointach", ale wbudujemy je w nasz konkretny serwis katalogu, który żyje już w trybie config-first. Idea jest bardzo prosta: health niech pozostaje zwięzły (bez szczegółów domyślnie), a info będzie zwracać zrozumiałą wizytówkę, przy czym nie zakodowaną na stałe w kodzie Java, lecz zebraną z konfiguracji. Bo skoro robimy Boot-template, to zróbmy go uczciwie: zmienia się konfiguracja – zmienia się i „paszport".

W src/main/resources/application.yaml można dodać (lub doprowadzić do takiej postaci) taki blok:

management:
  endpoint:
    health:
      # W bazowej konfiguracji ukrywamy szczegóły, żeby endpoint był bezpieczny domyślnie
      show-details: never
  info:
    env:
      # Zezwalamy na oddawanie info.* w /actuator/info
      enabled: true

info:
  app:
    # Bierzemy nazwę ze spring.application.name, żeby nie duplikować i nie rozjeżdżać
    name: ${spring.application.name}
    # Wizytówka powinna być krótka i neutralna
    description: "Read-only catalog of courses"
    # Przykład „czytelnej dla człowieka" nazwy katalogu z własnych właściwości
    catalog-title: ${app.catalog.title}
    # Na razie można trzymać wersję jako string, potem można to zautomatyzować
    version: "1.0.0"

Są tu dwa momenty szczególnie przydatne dla nowicjusza.

Pierwszy moment – placeholdery w postaci ${spring.application.name} i ${app.catalog.title}. Już pracowaliśmy z konfiguracją, więc to kontynuacja tej samej myśli: info to nie „ręczny JSON", to też warstwa, którą można powiązać ze źródłami właściwości. Wychodzi dość ładnie: zmieniasz spring.application.name lub app.catalog.title – i info automatycznie odzwierciedla rzeczywistość.

Drugi moment – granica. Celowo nie wkładamy tu „wszystkiego". Na przykład nie wkładamy pełnej listy kursów. Nie wkładamy całego konfiga. Nie wkładamy zmiennych środowiskowych. info musi pozostać krótkie i bezpieczne.

Jeśli w profilu lokalnym chcesz trochę więcej wygody, możesz odróżnić local od innych środowisk. Na przykład w application-local.yaml możesz dodać pole „environment", żeby bezpośrednio w JSON było widać, gdzie jesteś:

info:
  app:
    # Wyraźna oznaczenie środowiska pomaga nie zgadywać, który profil jest teraz aktywny
    environment: "local"

Wtedy /actuator/info będzie zwracać dodatkowo environment i nie będziesz się zastanawiać „czy teraz jestem w local, czy przypadkowo włączyłem dev?". To drobiazg, ale świetnie oszczędza czas i nerwy.

6. Typowe błędy przy pracy z health i info

Gdy zaczynasz używać Actuatora, błędy są zazwyczaj nie „składniowe", lecz „semantyczne". Czyli aplikacja startuje, endpoint odpowiada, ale przypadkowo budujesz sobie (lub kolegom) niewygodną lub niebezpieczną diagnostyczną powierzchnię. Poniżej – najczęstsze grabie, na które trafia się właśnie na poziomie bazowym, gdy chce się jak najszybciej zobaczyć „więcej przydatnego".

Błąd №1: oczekiwanie od health, że będzie pełnym raportem debug.
health to szybki wskaźnik stanu, a nie opowieść „dlaczego u mnie nie zadziałał filtr track=SPRING". Jeśli postrzegasz health jako uniwersalną diagnostykę, albo ciągle będziesz rozczarowany („a gdzie szczegóły?"), albo włączysz szczegóły na zawsze i zrobisz endpoint zbyt gadatliwym. Lepiej trzymać health jako krótki sygnał, a głębię włączać świadomie i dozowanie.

Błąd №2: włączenie show-details: always „dla wygody" i zapomnienie, że może to trafić dalej niż środowisko lokalne.
Lokalnie szczegółowy health jest rzeczywiście przyjemny. Ale jeśli trzymasz go włączonego we wszystkich profilach, stopniowo przyzwyczajasz się do „gadatliwości" i możesz ją przypadkowo zostawić tam, gdzie jest już nieodpowiednia. Profile nie są dla urody: wygodnie przez nie utrwalić, że lokalnie można więcej szczegółów, a w bardziej rygorystycznym środowisku – mniej.

Błąd №3: zamienianie info w „dump całego świata konfiguracyjnego".
info to wizytówka, a nie „oto mój application.yaml, cieszcie się". Jeśli do info trafiają przypadkowe wartości ze środowiska, URL-e, wewnętrzne flagi i wszystko po kolei, endpoint przestaje być zrozumiały i bezpieczny. Poza tym sam potem nie możesz szybko zrozumieć, co tam jest ważne, a co to po prostu „szum dla szumu".

Błąd №4: zapomnienie o management.info.env.enabled i potem dziwienie się, że info.* „nie działa".
Bardzo typowa sytuacja: dodałeś w application.yaml blok info: ..., zrestartowałeś aplikację, otworzyłeś /actuator/info, a tam pusto (lub prawie pusto). Pojawia się poczucie „coś napisałem nie tak". W rzeczywistości po prostu nie włączyłeś env-kontrybutora do info. Lepiej postrzegać to jako kolejną lekcję Boot: wiele rzeczy nie jest „magicznie włączone", lecz zarządzanych przez konfigurację.

Błąd №5: mieszanie „tożsamości aplikacji" i „danych domenowych" w info.
info nie powinien zamieniać się w „mini-API katalogu", gdzie leży np. lista kursów, liczba featured-kursów lub szczegóły filtrowania. Te rzeczy dotyczą domenowego API (/api/catalog/...) lub osobnej diagnostyki, ale nie wizytówki serwisu. Dobra zasada: jeśli dane często się zmieniają i są encjami biznesowymi – nie ma dla nich miejsca w info.

1
Zadanie
Spring Boot, poziom 22, lekcja 1
Niedostępne
Krótki `health` bez szczegółów
Krótki `health` bez szczegółów
1
Zadanie
Spring Boot, poziom 22, lekcja 1
Niedostępne
Karta serwisowa aplikacji przez `info`
Karta serwisowa aplikacji przez `info`
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION