W poprzednim rozdziale pokazaliśmy jak monitorować aplikacje oparte o Spring Boot 1.x. Teraz omówimy jak wygląda to zagadnienie w przypadku Spring Boota 2.x.
Razem z drugą wersją Spring Boot-a wprowadzona została też druga wersja mechanizmu
Actuator. Tak samo jak poprzednio dołączamy ją do projektu
wprowadzając zależność:
Wstępna konfiguracja w pliku
application.properties powinna wyglądać podobnie jak w przypadku wersji pierwszej, jednak
trzeba mieć na uwadze, że zmieniły się nieco nazwy własności. Dodane zostało słowo
server. Od teraz mamy:
Przypomnijmy, że w ten sposób określamy
port, na którym będzie działała usługa. Ze względów bezpieczeństwa dobrze jest wybrać port inny niż ten, na którym pracuje nasza aplikacja.
Dodatkowo możemy określić
adres ip, z którego będzie można korzystać z usługi. To również jest zalecane.
W trakcie przeprowadzania testów warto jest włączyć wszystkie endpointy, gdyż domyślnie większość z nich jest wyłączona:
Oczywiście musimy uważać, żeby takiego ustawienia nie wdrożyć niezabezpieczonego hasłem na produkcji, gdyż będzie to miało katastrofalne skutki
w kontekście bezpieczeństwa.
Endpointy
Do
Actuatora w wersji drugiej dostejmy się z poziomu przeglądarki używając url-a (na przykładzie znanego nam już endpointa
health):
W obecnej wersji mamy dostępnych kilka nowych endpointów, jednakże najpierw chcielibyśmy pokazać endpoint, którego nie opisaliśmy w wersji pierwszej, a jednak
wydaje się być ważny. Jeśli w pliku
application.properties zdefiniujemy własność
logging.file lub
logging.path
wówczas możemy zajrzeć do naszych plików z logami bezpośrednio z poziomu konsoli webowej. Jest to szczególnie przydatne wtedy, gdy nie mamy dostępu do
logów na produkcji z poziomu serwera.
-
logfile
Wyświetla logi w przeglądarce jeśli została zdefiniowana własność logging.file lub logging.path:
Nowe Endpointy
Tak jak wspomnieliśmy nowy
Actuator to również nowe endpointy. Nam wpadły w oko - endpoint pokazujący konfigurację zadań automatycznych (schedulerów) zdefiniowanych
w aplikacji oraz odświeżony mechanizm śledzenia w postaci
httptrace:
-
scheduledtasks
Wyświetla schedulery z podziałem na typy wraz z podaniem ścieżki do klasy i metody, dla której dany scheduler jest zdefiniowany:
-
httptrace
Wyświetla informacje o ruchu w aplikacji, podobny do trace znanego z poprzedniej wersji Actuatora. Teraz jednak jest bardziej
skondensowany (zawiera tylko kluczowe dane http), przez co jest bardziej przejrzysty:
Endpoint metrics
Nazwa tego endpointa występowała już co prawda w poprzedniej wersji, ale teraz mamy do czynienia z całkowicie nowym silnikiem ukrytym pod jego "maską".
Actuator 2.x bazuje na rozwiązaniu
Micrometer i dostarcza nam beana o nazwie
MeterRegistry.
-
metrics
Tak jak poprzednio wyświetla zbiór informacji o stanie zasobów oraz szereg innych danych diagnostycznych. W porównaniu do poprzedniej wersji informacje te zawierają więcej metadanych.
Ze względu na ilość informacji zostały one podzielone na osobne sekcje, a więc odpalając sam endpoint metrics dostajemy teraz jedynie
listę dostępnych metryk:
I teraz jeśli interesuje nas na przykład bieżące zużycie procesora w trakcie wykonywania pracy przez aplikację wystarczy, że podamy odpowiednią nazwę własności w url-u (system.cpu.usage).
Własny endpoint
Przygotowanie customowego endpointa w nowej wersji
Actuatora wygląda zupełnie inaczej niż miało to miejsce wcześniej. Spowodowane jest
to tym, że mechanizm całego
Actuatora przestał współpracować tylko i wyłącznie z Spring MVC. Stał się niezależny od technologii.
Wprowadzone zostały rozwiązania generyczne do tworzenia endpointów.
Klasa, to zwykły komponent Springa, ale już pozostałe adnotacje pochodzą z biblioteki
spring-boot-actuator i są niezależne od frameworka.
Można ich użyć zarówno ze
Spring MVC jak i
Spring Webflux-em, czy nawet z Jerseyem.
Nasz endpoint został stworzony do przechowywania parametrów definiowanych przez nas w celu gromadzenia dodatkowych informacji o pracy systemu.
Dla przykładu wprowadziliśmy mapę z domyślnie ustawionymi wartościami
lastDeploymentAuthor oraz
lastDeploymentIssue.
Następnie przygotowaliśmy metody wykorzystujące tą mapę, opisując je adnotacjami mapującymi konkretne metody HTTP:
-
@ReadOperation - GET
-
@WriteOperation - POST
-
@DeleteOperation - DELETE
Dodatkowo użyliśmy adnotacji
@Selector, której zadaniem jest dopasowanie parametru metody do parametru w
URL. Zobaczmy teraz jak będzie
wyglądało pobranie wszystkich parametrów (metodą GET):
Tak będzie wyglądało pobranie wartości parametru po jego nazwie (metodą GET):
A tak wykonamy zmianę wartości parametru (metodą POST):
To co powinno zwrócić naszą uwagę to fakt, że nadal używamy nazwy parametru, który chcemy ustawić oraz to, że dane przesyłamy w postaci JSON-a, gdzie
value
to
nazwa parametru w metodzie. W rezultacie wywołując ponownie metodę GET pobierającą wszystkie parametry powinniśmy uzyskać widok podobny do tego:
Oczywiście jako parametr możemy przesłać również cały obiekt. Wówczas kolejne pola w JSON-ie będą mapowane na odpowiednie pola w obiekcie.
Na koniec zostaje nam metoda DELETE, ale jej nie będziemy już analizować. Wywołanie wygląda analogicznie do metody GET z parametrem.
Ciekawostka. Dokumentacja Spring Boota wspomina, że aby powyższe "zabawy" z parametrami w ogóle zadziałały, należy skompilować kod
(implementujący endpointa) z opcją -parameters. W przypadku, gdy używamy Mavena wraz z parentem ustawionym na spring-boot-starter-parent, nie powinno być wymagane
dodawanie tej opcji, powinno to działać automatycznie. Niemniej mogą nadal wystąpić problemy podczas testów w IDE. W przypadku Eclipse pomaga włączenie opcji
kompilatora (w preferencjach wyszukujemy Java Compiler) o nazwie "Store information about method parameters (usable via reflection)". W Intellij w miejscu konfirguracji kompilatora
należy wpisać -parameters, w sekcji "Additional command line parameters".
Bezpieczeństwo ponad wszystko
Tak jak w życiu, tak samo w przypadku systemów informatycznych szczególnie ważne jest odpowiednie zabezpieczenie cennych zasobów przed niepowołanym dostępem.
W przypadku
Actuatora ze Spring Boot-a 2 załatwiamy sprawę w standardowy sposób, to znaczy zgodny z szablonowym modelem bezpieczeństwa aplikacji.
Tak więc wystarczy nam stworzenie prostej konfiguracji security, na przykład:
Oczywiście powyższy przykład jest trywialny, choćby z tego powodu, że zawiera tylko zabezpieczenia dotyczące
Actuatora.
W rzeczywistości będziemy tutaj mieli wspólny model bezpieczeństwa zarówno dla aplikacji jak i dla
Actuatora.
Załóżmy jednak dla ułatwienia, że nasze zabezpieczenia wyglądają tak jak w przykładzie. W tym momencie nie dostaniemy się do żadnych endpointów (poza
health
i
info) jeśli nie posiadamy wymaganej roli. Testując taką konfigurację na naszym własnym endpoincie otrzymamy
AccessDenied:
W ten sposób określamy, które endpointy powinny być widoczne i dla kogo, a które nie. Tym samym nie używamy już konfiguracji znanej z
Actuatora 1.x opartej o
własność
sensitive. Przy próbie użycia własności
endpoints.sensitive zostaniemy poinformowani przez nasze IDE
(w tym przypadku Eclipse), że własność została zdeprecjonowana:
W bieżącym rozdziale przyjrzeliśmy się temu jak działa
Actuator w Spring Boot 2. Jeśli dla kogoś z Was zgromadzony tutaj materiał nie jest wystarczający, polecamy zapoznać się z linkami poniżej.
Wstawiliśmy tutaj odwołania zarówno do dokumentacji Spring Boota 2 jak również do dokumentacji API
Actuatora.
Linki
https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/reference/html/production-ready-endpoints.html
https://docs.spring.io/spring-boot/docs/2.0.x/actuator-api/html