Cześć wszystkim, z wami trzeci post z serii o Quarkus!

Podczas rozwoju mikrousług w Javie często uważa się, że i to oddzielne i niezależne od siebie API. Domyślnie programiści zazwyczaj korzystają z tych API, do których są już przyzwyczajeni, ponieważ nauka nowych frameworków i komponentów runtime zajmuje dużo czasu. Dziś spróbujemy ułatwić opanowanie niektórych popularnych i pokażemy, jak jednocześnie wykorzystać API Spring oraz nowe, przydatne możliwości .
Jeśli przejdziemy nieco głębiej, najpierw omówimy obszar zastosowania i szczegóły dotyczące tego, jak Quarkus wspiera interfejsy API Spring, aby pokazać programistom Spring, jak mogą stosować API MicroProfile w swojej codziennej pracy. Następnie opowiemy o API MicroProfile, które będą przydatne programistom Spring w tworzeniu mikrousług.
Dlaczego akurat Quarkus? Po pierwsze, to kodowanie na żywo (live coding), czyli automatyczne przeładowanie wszelkich zmian w API MicroProfile, API Spring i innych API Javy, które wykonuje się jednym poleceniem: mvn quarkus:dev. Po drugie, omawiany w serwis Person (kompilowany z interfejsów API Spring, MicroProfile i JPA do pliku binarnego przy użyciu natywnego obrazu GraalVM) uruchamia się w zaledwie 0,055 sekundy i zajmuje około 90 MB pamięci RAM (RSS) na końcowym punkcie aplikacji RESTful. W dodatku jego kompilacja odbywa się przy pomocy jednego polecenia: mvn package -Pnative.
Nie będziemy zagłębiać się w szczegóły MicroProfile, a jedynie postaramy się pomóc programistom Spring zrozumieć, jak w Quarkus można używać interfejsów API Spring razem z interfejsami API MicroProfile.
Kontenery i Kubernetes
Aby nie przeciążać tego artykułu, omówimy tutaj jedynie ogólne aspekty wsparcia , co jest ważne do zrozumienia. Quarkus pozycjonuje się jako Java stack dla Kubernetes, ma na celu minimalizację zużycia pamięci i czasu uruchamiania aplikacji Java i usług, co z kolei zwiększa gęstość ich rozmieszczenia na hoście i obniża całkowite koszty.
Quarkus również zasobów Kubernetes i oferuje dotyczące wdrażania na platformach Kubernetes i Red Hat OpenShift. Ponadto Quarkus automatycznie generuje pliki Dockerfile.jvm (opakowanie JVM) i Dockerfile.native (opakowanie dla binariów natywnych), które są niezbędne do tworzenia kontenerów.
I wreszcie, bazując na Kubernetes jako docelowym środowisku wdrożeniowym, Quarkus nie używa frameworków Java w przypadkach, gdy podobna funkcjonalność jest wdrożona na poziomie samej platformy Kubernetes. W tabeli 1 przedstawiona jest mapa zgodności funkcjonalnej Kubernetes i typowych frameworków Java stosowanych przez deweloperów Spring.
Tabela 1. Mapa zgodności frameworków Java i Kubernetes.
Funkcjonalność
Tradycyjny Spring Boot
Kubernetes
Odkrywanie usług
Eureka
DNS
Konfiguracja
Spring Cloud Config
Config Maps / Secrets
Obciążenie równoważenie
Ribbon (po stronie klienta)
Usługa, Replication Controller (po stronie serwera)
Kompilacja i uruchomienie kodu z przykładu
W tym artykule odnosimy się do , w którym współdzielone są interfejsy API Spring i MicroProfile, a nawet ten sam klas Java. Kod z tego przykładu można skompilować i uruchomić z linii poleceń, więcej informacji w pliku README.md.
Interfejsy API Spring Framework
Wstrzykiwanie zależności
Quarkus obsługuje szereg oraz interfejsów API Spring Dependency Injection (Spring DI). Jeśli pracujesz z MicroProfile, , to już dobrze znasz CDI. Z drugiej strony, deweloperzy Spring mogą używać Quarkus Extension for Spring DI API, aby zapewnić zgodność z Spring DI. Przykłady użycia wspieranych API Spring DI są przedstawione w tabeli 2.
W zastosowano zarówno CDI, jak i Spring Dependency Injection. Dodatkowe informacje i przykłady na ten temat można znaleźć w przewodniku Quarkus zatytułowanym .
Tabela 2. Przykłady użycia wspieranych interfejsów API Spring DI.
Wspierane funkcje Spring DI
Przykłady
Wstrzykiwanie konstruktora
public PersonSpringController(
PersonSpringRepository personRepository, // wstrzyknięte
PersonSpringMPService personService) { // wstrzyknięte
this.personRepository = personRepository;
this.personService = personService;
}
Wstrzykiwanie pola
@Autowired
@RestClient
SalutationRestClient salutationRestClient;
@Value("${fallbackSalutation}")
String fallbackSalutation;
@Configuration
@Configuration
public class AppConfiguration {
@Bean(name = "capitalizeFunction")
public StringFunction capitalizer() {
return String::toUpperCase;
}
}
@Component("noopFunction")
public class NoOpSingleStringFunction implements StringFunction {
@Override
public String apply(String s) {
return s;
}
}
@Service
public class MessageProducer {
@Value("${greeting.message}")
String message;
public String getPrefix() {
return message;
}
}
Framework webowy
Użytkownikom MicroProfile spodoba się, że Quarkus obsługuje JAX-RS, MicroProfile Rest Client, JSON-P i JSON-B jako główny model programowania aplikacji webowych. Programiści Spring będą zadowoleni z nowo wprowadzonego wsparcia dla Spring Web API w Quarkus, w szczególności interfejsów odpowiedzialnych za REST. Podobnie jak w przypadku Spring DI, głównym celem wsparcia dla Spring Web API jest umożliwienie programistom Spring korzystania z interfejsów API Spring Web wraz z interfejsami API MicroProfile. Przykłady wykorzystania wspieranych interfejsów API Spring Web przedstawione są w tabeli 3, a dodatkowe informacje i przykłady można znaleźć w przewodniku Quarkus o nazwie .
Tabela 3. Przykłady zastosowania wspieranych interfejsów API Spring Web.
Obsługiwane funkcje Spring Web
Przykłady
@RestController
@RequestMapping
@RestController
@RequestMapping("/person")
public class PersonSpringController {
...
...
...
}
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
@RequestParam
@RequestHeader
@MatrixVariable
@PathVariable
@CookieValue
@RequestBody
@ResponseStatus
@ExceptionHandler
@RestControllerAdvice (częściowo)
@GetMapping(path = "/greet/{id}",
produces = "text/plain")
public String greetPerson(
@PathVariable(name = "id") long id) {
...
...
...
}
Spring Data JPA
Użytkownikom MicroProfile również przypadnie do gustu, że Quarkus obsługuje JPA przy użyciu Hibernate ORM. Dla programistów Spring też jest dobra wiadomość: Quarkus obsługuje powszechnie stosowane adnotacje i typy Spring Data JPA. Przykłady użycia wspieranych interfejsów API Spring Data JPA przedstawione są w tabeli 4.
W wspierane są interfejsy API Spring Data JPA, a dodatkowe informacje dostępne są w przewodniku Quarkus o nazwie .
Tabela 4. Przykłady zastosowania wspieranych interfejsów API Spring Data JPA.
Obsługiwane funkcje Spring Data JPA
Przykłady
CrudRepository
public interface PersonRepository
extends JpaRepository,
PersonFragment {
...
}
Repozytorium
JpaRepository
PagingAndSortingRepository
public class PersonRepository extends
Repository {
Person save(Person entity);
Optional findById(Person entity);
}
Fragmenty repozytoriów
public interface PersonRepository
extends JpaRepository,
PersonFragment {
...
}
Metody zapytań pochodnych
public interface PersonRepository extends CrudRepository {
List findByName(String name);
Person findByNameBySsn(String ssn);
Optional
findByNameBySsnIgnoreCase(String ssn);
Boolean existsBookByYearOfBirthBetween(
Integer start, Integer end);
}
Zapytania zdefiniowane przez użytkownika
public interface MovieRepository
extends CrudRepository {
Movie findFirstByOrderByDurationDesc();
@Query("select m from Movie m where m.rating = ?1")
Iterator findByRating(String rating);
@Query("from Movie where title = ?1")
Movie findByTitle(String title);
}
Interfejsy API MicroProfile
Tolerancja na błędy (Fault tolerance)
Konstrukcje wysokiej dostępności są bardzo ważne, aby zapobiegać awariom kaskadowym i tworzyć niezawodne architektury mikroserwisowe. Programiści Spring od lat korzystają z circuit-breaker'ów w celu zapewnienia odporności na awarie. . Jednak Hystrix od dłuższego czasu nie był aktualizowany, a API MicroProfile Fault Tolerance jest aktywnie rozwijane i ma już za sobą kilka lat użytkowania w produkcji. Dlatego w celu zwiększenia niezawodności usług w Quarkus zaleca się korzystanie z interfejsów API MicroProfile Fault Tolerance, a przykłady ich użycia są przedstawione w tabeli 5. Dodatkowe informacje można znaleźć w przewodniku Quarkus. .
Tabela 5. Przykłady użycia obsługiwanych interfejsów API MicroProfile Fault Tolerance.
Funkcje MicroProfile Fault Tolerance
Opis
Przykłady
@Asynchronous
Wykonywanie logiki w osobnym wątku
@Asynchronous
@Retry
public Future getSalutation() {
...
return future;
}
@Bulkhead
Ograniczenie liczby jednoczesnych żądań
@Bulkhead(5)
public void fiveConcurrent() {
makeRemoteCall(); //...
}
@CircuitBreaker
Inteligentne przetwarzanie błędów i odzyskiwanie po awariach
@CircuitBreaker(delay=500 // milisekundy
failureRatio = .75,
requestVolumeThreshold = 20,
successThreshold = 5)
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
makeRemoteCall(); //...
}
@Fallback
Wywołanie alternatywnej logiki w przypadku awarii
@Timeout(500) // milisekundy
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
makeRemoteCall(); //...
}
public String fallback() {
return "hello";
}
Powtórzenie w przypadku awarii żądania
@Retry(maxRetries=3)
public String getSalutation() {
makeRemoteCall(); //...
}
Czas oczekiwania w przypadku awarii
@Timeout(value = 500) // milisekundy
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
makeRemoteCall(); //...
}
Sprawdzanie stanu usług (Service Health)
Platformy Kubernetes monitorują stan kontenerów za pomocą specjalnych usług. Aby dolna platforma mogła monitorować usługi, programiści Spring zazwyczaj korzystają z konfigurowalnych HealthIndicator i Spring Boot Actuator. W Quarkus można to zrealizować za pomocą MicroProfile Health, które domyślnie wykonują sprawdzenie stanu (liveness check), ale mogą być także skonfigurowane do jednoczesnego sprawdzania liveness i readiness (gotowości). Przykłady użycia obsługiwanych interfejsów API MicroProfile Health przedstawione są w tabeli 6, a dodatkowe informacje zawarte są w przewodniku Quarkus. .
Tabela 6. Przykłady użycia obsługiwanych interfejsów API MicroProfile Health.
Funkcje MicroProfile Health
Opis
Przykłady
@Liveness
Platforma przeprowadza ponowne uruchomienie uszkodzonych aplikacji kontenerowych
Endpoint:
host:8080/health/live
@Liveness
public class MyHC implements HealthCheck {
public HealthCheckResponse call() {
...
return HealthCheckResponse
.named("myHCProbe")
.status(ready ? true:false)
.withData("mydata", data)
.build();
}
@Readiness
Platforma nie będzie kierować ruchu do kontenerizowanej aplikacji, jeśli będzie ona niegotowa
Endpoint:
host:8080/health/ready
@Readiness
public class MyHC implements HealthCheck {
public HealthCheckResponse call() {
...
return HealthCheckResponse
.named("myHCProbe")
.status(live ? true:false)
.withData("mydata", data)
.build();
}
Metryki
Aplikacje dostarczają metryki zarówno w celach operacyjnych (do monitorowania wskaźników wydajności SLA), jak i nieoperacyjnych (wskaźniki biznesowe SLA). Programiści Spring dostarczają metryki za pomocą Spring Boot Actuator i Micrometer. Z kolei Quarkus wykorzystuje MicroProfile Metrics do dostarczania podstawowych metryk (JVM i system operacyjny), metryk dostawców (Quarkus) i metryk aplikacji. MicroProfile Metrics wymaga, aby implementacja wspierała formaty wyjściowe JSON i OpenMetrics (Prometheus). Przykłady użycia API MicroProfile Metrics są podane w tabeli 7.
W MicroProfile Metrics są używane do dostarczania metryk aplikacji. Dalsze informacje można znaleźć w przewodniku Quarkus .
Tabela 7. Przykłady użycia interfejsów API MicroProfile Metrics.
Funkcje MicroProfile Metrics
Opis
Przykłady
@Counted
Oznacza licznik, który zlicza liczbę wywołań oznaczonego obiektu
@Counted(name = "fallbackCounter",
displayName = "Fallback Counter",
description = "Fallback Counter")
public String salutationFallback() {
return fallbackSalutation;
}
@ConcurrentGauge
Oznacza wskaźnik, który zlicza liczbę równoległych wywołań oznaczonego obiektu
@ConcurrentGuage(
name = "fallbackConcurrentGauge",
displayName="Fallback Concurrent",
description="Fallback Concurrent")
public String salutationFallback() {
return fallbackSalutation;
}
@Gauge
Oznacza wskaźnik, który mierzy wartość oznaczonego obiektu
@Metered(name = "FallbackGauge",
displayName="Fallback Gauge",
description="Fallback frequency")
public String salutationFallback() {
return fallbackSalutation;
}
@Metered
Oznacza wskaźnik, który śledzi częstotliwość wywołań oznaczonego obiektu
@Metered(name = "MeteredFallback",
displayName="Metered Fallback",
description="Fallback frequency")
public String salutationFallback() {
return fallbackSalutation;
}
Adnotacja zawierająca informacje o metadanych, w momencie zapytania o utworzenie lub produkcję metryki
@Metric
@Metered(name = "MeteredFallback",
displayName="Metered Fallback",
description="Fallback frequency")
public String salutationFallback() {
return fallbackSalutation;
}
Oznacza timer, który śledzi czas trwania oznaczonego obiektu
@Timed(name = "TimedFallback",
displayName="Timed Fallback",
description="Fallback delay")
public String salutationFallback() {
return fallbackSalutation;
}
Punkty końcowe metryk
Metryki aplikacji :8080/metrics/application
Podstawowe metryki :8080/metrics/base
Metryki dostawcy :8080/metrics/vendor
Wszystkie metryki :8080/metrics
Klient REST MicroProfile
Mikroserwisy często udostępniają punkty końcowe RESTful, do których obługi wymagane są odpowiednie API klientów. Aby korzystać z punktów końcowych RESTful, deweloperzy Springa zazwyczaj używają RestTemplate. Quarkus oferuje jednak API MicroProfile Rest Client do tego celu, a przykłady jego użycia podano w tabeli 8.
W Użycie punktów końcowych RESTful jest realizowane za pomocą MicroProfile Rest Client. Dodatkowe informacje i przykłady na ten temat można znaleźć w przewodniku Quarkus. .
Tabela 8. Przykłady użycia API MicroProfile Rest Client.
Funkcje MicroProfile Rest Client
Opis
Przykłady
@RegisterRestClient
Rejestruje typizowany interfejs Java jako klienta REST
@RegisterRestClient
@Path("/")
public interface MyRestClient {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getSalutation();
}
@RestClient
Oznacza wstrzyknięcie instancji typizowanego interfejsu klienta REST
@Autowired // or @Inject
@RestClient
MyRestClient restClient;
Wywołanie
Wywołuje punkt końcowy REST
System.out.println(
restClient.getSalutation());
mp-rest/url
Ustala punkt końcowy REST
application.properties:
org.example.MyRestClient/mp-rest/url=
http://localhost:8081/myendpoint
Podsumowanie
W tym blogu, który przede wszystkim będzie przydatny dla deweloperów Springa, krótko omówiliśmy, jak w Quarkus używać interfejsów API Springa razem z API MicroProfile do tworzenia mikroserwisów Java, a następnie kompilować je do natywnego kodu binarnego, co oszczędza setki megabajtów pamięci RAM i uruchamia się w kilka milisekund.
Jak już zrozumieliście, dodatkowe informacje o wsparciu dla interfejsów API Spring i MicroProfile oraz wiele innych przydatnych informacji można znaleźć w .
Źródło: habr.com
