Cum Quarkus îmbină MicroProfile și Spring

Salut tuturor, și sunteți cu al treilea articol din seria despre Quarkus!

Cum Quarkus îmbină MicroProfile și Spring

În dezvoltarea microserviciilor Java, se consideră adesea că Eclipse MicroProfile și Spring Boot – acestea sunt API-uri separate și independente unul de celălalt. În mod obișnuit, programatorii folosesc API-urile la care sunt deja obișnuiți, deoarece învățarea unor noi cadre și componente runtime necesită mult timp. Astăzi, vom încerca să simplificăm învățarea unor API-uri MicroProfile populare pentru dezvoltatorii Spring și vom arăta cum să folosești simultan API-urile Spring și noi funcționalități utile Quarkus.

Dacă ne adâncim puțin, vom examina domeniul de aplicare și detalii despre cum Quarkus suportă interfețele API Spring, pentru a arăta dezvoltatorilor Spring cum pot utiliza API-urile MicroProfile în activitatea lor zilnică. Apoi, vom vorbi despre API-urile MicroProfile care vor fi utile dezvoltatorilor Spring la crearea de microservicii.

De ce anume Quarkus? În primul rând, este codare live, adică reîncărcare automată a oricăror modificări în API-urile MicroProfile, API-urile Spring și alte API-uri Java, care se realizează cu o singură comandă: mvn quarkus:dev. În al doilea rând, discutăm în exemplul nostru serviciul Person (compilat din interfețele API Spring, MicroProfile și JPA într-un fișier binar utilizând GraalVM nativ) pornește în doar 0,055 secunde și ocupă aproximativ 90 MB în memorie (RSS) pe punctul final al aplicației RESTful. În plus, compilarea sa se realizează cu un singur command: mvn package -Pnative.

Nu ne vom adânci în detaliile MicroProfile, ci vom încerca să ajutăm dezvoltatorii Spring să înțeleagă cum pot utiliza interfețele API Spring împreună cu interfețele API MicroProfile în Quarkus.

Containere și Kubernetes

Pentru a nu supraîncărca acest articol, vom examina aici doar aspectele de înalt nivel ale suportului Kubernetes, deoarece este important de înțeles. Quarkus este poziționat ca un stack Java pentru Kubernetes, având scopul de a minimiza consumul de memorie și timpul de pornire al aplicațiilor și serviciilor Java, și, ca urmare, de a spori densitatea lor de amplasare pe gazdă și a reduce costurile totale.

Quarkus de asemenea suportă generarea automată a resurselor Kubernetes și oferă ghid pentru desfășurarea pe platforme Kubernetes și Red Hat OpenShift. În plus, Quarkus generează automat fișierele Dockerfile.jvm (pachetare JVM) și Dockerfile.native (pachetare binară nativă), necesare pentru crearea containerelor.

Și, în cele din urmă, având în vedere Kubernetes ca mediu de desfășurare țintă, Quarkus nu utilizează cadre Java în cazurile în care o funcționalitate similară este realizată la nivelul platformei Kubernetes. În Tabelul 1 se prezintă o hartă a corespondenței funcționale între Kubernetes și cadrele Java tipice utilizate de dezvoltatorii Spring.

Tabelul 1. Harta corespondenței funcționale între cadrele Java și Kubernetes.

Funcționalitate
Spring Boot tradițional
Kubernetes

Service discovery
Eureka
DNS

Configurare
Spring Cloud Config
Config Maps / Secrets

Încărcarea echilibrată
Ribbon (pe partea clientului)
Service, Replication Controller (pe partea serverului)

Compilarea și rularea codului din exemplu

În acest articol ne referim la exemplul unui proiect, în care sunt utilizate împreună API-urile Spring și MicroProfile și chiar acel Java-class. Codul din acest exemplu poate fi compilat și rulat din linia de comandă, consultați fișierul README.md pentru detalii.

API-urile Spring Framework

Dependency Injection

Quarkus suportă o varietate de API-uri Contexts and Dependency Injection (CDI) și API-uri Spring Dependency Injection (Spring DI). Dacă lucrați cu MicroProfile, Java EE și Jakarta EE, atunci sunteți deja familiarizat cu CDI. Pe de altă parte, dezvoltatorii Spring pot utiliza Quarkus Extension for Spring DI API pentru a asigura compatibilitatea cu Spring DI. Exemplele de utilizare a API-urilor Spring DI acceptate sunt prezentate în Tabelul 2.

În proiectul din exemplul nostru folosește atât CDI, cât și Spring Dependency Injection. Informații suplimentare și exemple pe această temă pot fi găsite în ghidul Quarkus, cunoscut sub denumirea de Spring DI Guide.

Tabelul 2. Exemple de utilizare a API-urilor Spring DI acceptate.

Funcții acceptate de Spring DI
Exemple

Constructor Injection

public PersonSpringController(
   PersonSpringRepository personRepository,  // injected      
   PersonSpringMPService personService) {    // injected
      this.personRepository = personRepository;
      this.personService = personService;
}

Field Injection
Autowired
Value

@Autowired
@RestClient
SalutationRestClient salutationRestClient;

@Value("${fallbackSalutation}")
String fallbackSalutation;

Bean
@Configuration

@Configuration
public class AppConfiguration {
   @Bean(name = "capitalizeFunction")
   public StringFunction capitalizer() {
      return String::toUpperCase;
   }
}

Component

@Component("noopFunction")
public class NoOpSingleStringFunction implements StringFunction {
   @Override
   public String apply(String s) {
      return s;
   }
}

Serviciu

@Service
public class MessageProducer {
   @Value("${greeting.message}")
   String message;

   public String getPrefix() {
      return message;
   }
}

Cadru web

Utilizatorii MicroProfile se vor bucura că Quarkus suportă JAX-RS, MicroProfile Rest Client, JSON-P și JSON-B ca model principal de programare web. Dezvoltatorii Spring vor fi încântați de noua support pentru Spring Web API care a apărut recent în Quarkus, în special pentru interfețele care se ocupă de REST. Asemenea DI-ului din Spring, scopul principal al suportului pentru Spring Web API este ca dezvoltatorii Spring să poată folosi interfețele API Spring Web împreună cu cele ale MicroProfile. Exemplele de utilizare a API-urilor suportate de Spring Web sunt prezentate în tabelul 3, iar informații suplimentare și exemple pe această temă pot fi găsite în ghidul Quarkus intitulat Ghidul Spring Web.

Tabelul 3. Exemple de utilizare a API-urilor suportate de Spring Web.

Funcționalitățile suportate de Spring Web
Exemple

@RestController
@RequestMapping

@RestController
@RequestMapping("/person")
public class PersonSpringController {
   ...
   ...
   ...
}

@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
@RequestParam
@RequestHeader
@MatrixVariable
@PathVariable
@CookieValue
@RequestBody
@ResponseStatus
@ExceptionHandler
@RestControllerAdvice (parțial)

@GetMapping(path = "/greet/{id}",
   produces = "text/plain")
   public String greetPerson(
   @PathVariable(name = "id") long id) {
   ...
   ...
   ...
}

Spring Data JPA

Utilizatorii MicroProfile vor aprecia de asemenea că Quarkus suportă JPA folosind Hibernate ORM. De asemenea, existe vești bune pentru dezvoltatorii Spring: Quarkus acceptă anotații și tipuri comune din Spring Data JPA. Exemple de utilizare a API-urilor suportate de Spring Data JPA sunt prezentate în tabelul 4.
În proiectul din exemplul nostru se folosesc API-urile Spring Data JPA, iar informații suplimentare sunt disponibile în ghidul Quarkus intitulat Ghidul Spring Data JPA.

Tabelul 4. Exemple de utilizare a API-urilor suportate de Spring Data JPA.

Funcționalitățile suportate de Spring Data JPA
Exemple

CrudRepository

public interface PersonRepository
         extends JpaRepository,
                 PersonFragment {
   ...
}

Repository
JpaRepository
PagingAndSortingRepository

public class PersonRepository extends 

    Repository {

    Person save(Person entity);

    Optional findById(Person entity);
}

Fragmente de Repository

public interface PersonRepository
         extends JpaRepository,
                 PersonFragment {
   ...
}

Metode de interogare derivate

public interface PersonRepository extends CrudRepository {

    List findByName(String name);
    
    Person findByNameBySsn(String ssn);
    
    Optional 
       findByNameBySsnIgnoreCase(String ssn);

    Boolean existsBookByYearOfBirthBetween(
            Integer start, Integer end);
}

Interogări definite de utilizator

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

API-urile MicroProfile

Toleranță la defecte (Fault tolerance)

Conceptele de toleranță la defecte sunt foarte importante pentru a preveni defecțiunile în cascadă și pentru a crea arhitecturi de microservicii fiabile. Dezvoltatorii Spring folosesc de ani de zile circuit-breaker-e pentru toleranța la defecte. Hystrix. Cu toate acestea, Hystrix nu a fost actualizat de mult timp, în timp ce soluția Fault Tolerance din MicroProfile este acum activ dezvoltată și beneficiază deja de câțiva ani de utilizare în producție. Din acest motiv, pentru a crește fiabilitatea serviciilor în Quarkus, se recomandă folosirea interfețelor API MicroProfile Fault Tolerance, a căror utilizare este prezentată în tabelul 5. Informații suplimentare despre aceasta pot fi găsite în ghidul Quarkus. Ghid pentru Toleranța la Defecte.

Tabelul 5. Exemple de utilizare a interfețelor API suportate MicroProfile Fault Tolerance.

Funcții MicroProfile Fault Tolerance
Descriere
Exemple

@Asynchronous

Executarea logicii într-un fir de execuție separat.

@Asynchronous
@Retry
public Future getSalutation() {
   ...
   return future;
}

@Bulkhead

Limitarea numărului de cereri simultane.

@Bulkhead(5)
public void fiveConcurrent() {
   makeRemoteCall(); //...
}

@CircuitBreaker

Gestionarea inteligentă a erorilor și recuperarea după defecțiuni.

@CircuitBreaker(delay=500   // milisecunde
   failureRatio = .75,
   requestVolumeThreshold = 20,
   successThreshold = 5)
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
   makeRemoteCall(); //...
}

@Fallback

Apelarea unei logici alternative în caz de eșec.

@Timeout(500) // milisecunde
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
   makeRemoteCall(); //...
}

public String fallback() {
   return "hello";
}

Retry

Repetare în caz de eșec al cererii.

@Retry(maxRetries=3)
public String getSalutation() {
   makeRemoteCall(); //...
}

Timeout

Timpul de așteptare în cazul unei erori.

@Timeout(value = 500 )   // milisecunde
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
   makeRemoteCall(); //...
}

Verificarea serviciilor (Service Health)

Platformele Kubernetes monitorizează sănătatea containerelor prin servicii speciale. Pentru ca platforma de bază să poată monitoriza serviciile, dezvoltatorii Spring folosesc, de obicei, HealthIndicator personalizate și Spring Boot Actuator. În Quarkus, acest lucru se poate realiza prin MicroProfile Health, care, în mod implicit, efectuează verificări de sănătate (liveness check), dar pot fi configurate și pentru a efectua simultan verificări de liveness și readiness (pregătire). Exemplele de utilizare a interfețelor API MicroProfile Health suportate sunt prezentate în tabelul 6, iar informații suplimentare sunt disponibile în ghidul Quarkus. Ghid pentru Sănătate.

Tabelul 6. Exemple de utilizare a interfețelor API suportate MicroProfile Health.

Funcții MicroProfile Health
Descriere
Exemple

@Liveness

Platforma efectuează restartul aplicațiilor containerizate defecte.
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 nu va trimite trafic către aplicația containerizată în cazul în care nu este pregătită
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();  
}

Metrici

Aplicațiile oferă metrici fie în scopuri operaționale (pentru monitorizarea SLA-urilor de performanță), fie în scopuri non-operaționale (indicatori de afaceri SLA). Dezvoltatorii Spring oferă metrici prin Spring Boot Actuator și Micrometer. La rândul său, Quarkus utilizează MicroProfile Metrics pentru a oferi metrici de bază (JVM și sistem de operare), metrici de vendor (Quarkus) și metrici ale aplicațiilor. MicroProfile Metrics necesită ca implementarea să suporte formatele de ieșire JSON și OpenMetrics (Prometheus). Exemplele de utilizare a MicroProfile Metrics API sunt prezentate în Tabelul 7.

În proiectul din exemplul nostru MicroProfile Metrics sunt utilizate pentru a oferi metrici ale aplicației. Informații suplimentare pot fi găsite în ghidul Quarkus Metrics Guide.

Tabelul 7. Exemple de utilizare a API-urilor MicroProfile Metrics.

Funcții MicroProfile Metrics
Descriere
Exemple

@Counted

Indică un counter pentru a număra numărul de apeluri ale obiectului marcat

@Counted(name = "fallbackCounter", 
  displayName = "Fallback Counter", 
  description = "Fallback Counter")
public String salutationFallback() {
   return fallbackSalutation;
}

@ConcurrentGauge

Indică un gauge care numără numărul de apeluri paralele ale obiectului marcat

@ConcurrentGuage(
  name = "fallbackConcurrentGauge", 
  displayName="Fallback Concurrent", 
  description="Fallback Concurrent")
public String salutationFallback() {
   return fallbackSalutation;
}

@Gauge

Indică un gauge care măsoară valoarea obiectului marcat

@Metered(name = "FallbackGauge",
   displayName="Fallback Gauge",
   description="Fallback frequency")
public String salutationFallback() {
   return fallbackSalutation;
}

@Metered

Indică un meter care urmărește frecvența apelurilor obiectului marcat

@Metered(name = "MeteredFallback",
   displayName="Metered Fallback",
   description="Fallback frequency")
public String salutationFallback() {
   return fallbackSalutation;
}

Metric

Anotare care conține informații despre metadatele atunci când se face o solicitare pentru a introduce sau produce metrici

@Metric
@Metered(name = "MeteredFallback",
   displayName="Metered Fallback",
   description="Fallback frequency")
public String salutationFallback() {
   return fallbackSalutation;
}

Timed

Indică un timer care urmărește durata obiectului marcat

@Timed(name = "TimedFallback",
   displayName="Fallback temporizat",
   description="Întârziere de fallback")
public String salutationFallback() {
   return fallbackSalutation;
}

Puncte finale pentru metrici (Metrics Endpoints)

Metrici ale aplicațiilor localhost:8080/metrics/application
Metrici de bază localhost:8080/metrics/base
Metrici ale furnizorului localhost:8080/metrics/vendor
Toate metricile localhost:8080/metrics

Client REST MicroProfile

Microserviciile oferă adesea puncte finale RESTful, pentru a lucra cu care sunt necesare API-uri corespunzătoare pentru client. Pentru a utiliza punctele finale RESTful, dezvoltatorii Spring aplică de obicei RestTemplate. Quarkus, pe de altă parte, oferă API-uri MicroProfile Rest Client pentru a răspunde acestei nevoi, exemplele de utilizare fiind prezentate în Tabelul 8.

În proiectul din exemplul nostru Utilizarea punctelor finale RESTful se face prin intermediul MicroProfile Rest Client. Informații suplimentare și exemple pe această temă pot fi găsite în ghidul Quarkus Ghidul Clientului REST.

Tabelul 8. Exemple de utilizare a API-urilor MicroProfile Rest Client.

Funcționalități ale MicroProfile Rest Client
Descriere
Exemple

@RegisterRestClient

Înregistrează o interfață Java tipizată ca client REST

@RegisterRestClient
@Path("/")
public interface MyRestClient {
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getSalutation();
}

@RestClient

Marchează injectarea unei instanțe a interfeței tipizate pentru clientul REST

@Autowired // sau @Inject
@RestClient
MyRestClient restClient;

Invocare

Apelează un punct final REST

System.out.println(
   restClient.getSalutation());

mp-rest/url

Defineste punctul final REST

application.properties:
org.example.MyRestClient/mp-rest/url=
   http://localhost:8081/myendpoint

Concluzii

În acest blog, care va fi util în special dezvoltatorilor Spring, am analizat pe scurt cum se pot folosi API-urile Spring împreună cu cele MicroProfile în Quarkus pentru a dezvolta microservicii Java și apoi a le compila în cod binar nativ, economisind sute de megabytes de RAM și pornind în câteva milisecunde.

Așa cum ați înțeles, informații suplimentare despre suportul pentru API-urile Spring și MicroProfile, precum și multe alte informații utile pot fi găsite în ghidurile Quarkus.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster