Ciao a tutti, ecco il terzo post della serie su Quarkus!

Nello sviluppo di microservizi Java, spesso si considera che e sono API separate e indipendenti l'una dall'altra. Per impostazione predefinita, i programmatori tendono a utilizzare le API a cui sono già abituati, poiché l'apprendimento di nuovi framework e componenti di runtime richiede molto tempo. Oggi proveremo a semplificare l'apprendimento di alcune delle popolari e mostreremo come utilizzare simultaneamente le API di Spring e le nuove funzionalità utili .
Se vogliamo essere più dettagliati, prima esamineremo il campo di applicazione e i dettagli su come Quarkus supporta le interfacce API di Spring, per mostrare agli sviluppatori Spring come possono applicare le API MicroProfile nel loro lavoro quotidiano. Poi parleremo delle API MicroProfile che saranno utili agli sviluppatori Spring nella creazione di microservizi.
Perché proprio Quarkus? Innanzitutto, è il live coding, ovvero il riavvio automatico di qualsiasi modifica nelle API MicroProfile, nelle API di Spring e in altre API Java, che si esegue con un solo comando: mvn quarkus:dev. In secondo luogo, il servizio Person considerato nel compila dalle interfacce API di Spring, MicroProfile e JPA in un file binario utilizzando l'immagine nativa di GraalVM) si avvia in soli 0.055 secondi e occupa circa 90 MB di RAM (RSS) sulla punta finale dell'applicazione RESTful. La sua compilazione avviene con un solo comando: mvn package -Pnative.
Non approfondiremo i dettagli di MicroProfile, ma cercheremo di aiutare gli sviluppatori Spring a capire come in Quarkus si possano utilizzare le interfacce API di Spring insieme alle API di MicroProfile.
Contenitori e Kubernetes
Per non appesantire questo articolo, qui considereremo solo gli aspetti ad alto livello del supporto , poiché è importante comprenderlo. Quarkus è posizionato come uno stack Java per Kubernetes, destinato a minimizzare il consumo di memoria e il tempo di avvio delle applicazioni Java e dei servizi, aumentando di conseguenza la densità della loro distribuzione sull'host e riducendo i costi complessivi.
Quarkus supporta anche di risorse Kubernetes e offre per il deployment su piattaforme Kubernetes e Red Hat OpenShift. Inoltre, Quarkus genera automaticamente i file Dockerfile.jvm (packaging JVM) e Dockerfile.native (packaging binario nativo), necessari per la creazione dei contenitori.
Infine, orientandosi su Kubernetes come ambiente di distribuzione, Quarkus non utilizza framework Java nei casi in cui funzionalità simili siano implementate a livello della piattaforma Kubernetes stessa. Nella tabella 1 viene presentata una mappa di corrispondenza funzionale tra Kubernetes e i tipici framework Java utilizzati dagli sviluppatori Spring.
Tabella 1. Mappa di corrispondenza dei framework Java e Kubernetes.
Funzionalità
Tradizionale Spring Boot
Kubernetes
Service discovery
Eureka
DNS
Configurazione
Spring Cloud Config
Config Maps / Secrets
Bilanciamento del carico
Ribbon (lato client)
Service, Replication Controller (lato server)
Compilazione e avvio del codice dell'esempio
In questo articolo ci riferiamo a , dove sono utilizzate insieme le API di Spring e MicroProfile e persino quel Java class. Il codice di questo esempio può essere compilato e avviato dalla riga di comando, vedere il file README.md per ulteriori dettagli.
API di Spring Framework
Dependency Injection
Quarkus supporta una serie di e API di Spring Dependency Injection (Spring DI). Se lavori con MicroProfile, , allora sei già a conoscenza di CDI. D'altra parte, gli sviluppatori Spring possono utilizzare l'estensione Quarkus per l'API Spring DI per garantire la compatibilità con Spring DI. Esempi di utilizzo delle API Spring DI supportate sono riportati nella tabella 2.
In viene utilizzato sia CDI che Spring Dependency Injection. Maggiori dettagli e esempi su questo argomento possono essere trovati nella guida Quarkus intitolata .
Tabella 2. Esempi di utilizzo delle API Spring DI supportate.
Funzionalità supportate da Spring DI
Esempi
Constructor Injection
public PersonSpringController(
PersonSpringRepository personRepository, // iniettato
PersonSpringMPService personService) { // iniettato
this.personRepository = personRepository;
this.personService = personService;
}
Field Injection
@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;
}
}
Web framework
Gli utenti di MicroProfile apprezzeranno il supporto di Quarkus per JAX-RS, MicroProfile Rest Client, JSON-P e JSON-B come il modello principale di programmazione web. Gli sviluppatori Spring saranno felici di scoprire che Quarkus ha recentemente introdotto il supporto per le Spring Web API, in particolare per le interfacce che gestiscono il REST. Analogamente a Spring DI, l'obiettivo principale del supporto per le Spring Web API è consentire agli sviluppatori Spring di utilizzare le interfacce API di Spring Web insieme alle interfacce API di MicroProfile. Esempi di utilizzo delle Spring Web API supportate sono riportati nella tabella 3, mentre ulteriori informazioni e esempi su questo argomento possono essere trovati nella guida di Quarkus intitolata .
Tabella 3. Esempi di utilizzo delle interfacce API di Spring Web supportate.
Funzioni supportate da Spring Web
Esempi
@RestController
@RequestMapping
@RestController
@RequestMapping("/person")
public class PersonSpringController {
...
...
...
}
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
@RequestParam
@RequestHeader
@MatrixVariable
@PathVariable
@CookieValue
@RequestBody
@ResponseStatus
@ExceptionHandler
@RestControllerAdvice (parziale)
@GetMapping(path = "/greet/{id}",
produces = "text/plain")
public String greetPerson(
@PathVariable(name = "id") long id) {
...
...
...
}
Spring Data JPA
Anche agli utenti di MicroProfile piacerà che Quarkus supporta JPA utilizzando Hibernate ORM. Buone notizie anche per gli sviluppatori Spring: Quarkus supporta le annotazioni e i tipi standard di Spring Data JPA. Esempi di utilizzo delle API di Spring Data JPA supportate sono riportati nella tabella 4.
In vengono utilizzate le interfacce API di Spring Data JPA, e ulteriori informazioni sono disponibili nella guida di Quarkus intitolata .
Tabella 4. Esempi di utilizzo delle interfacce API di Spring Data JPA supportate.
Funzioni supportate da Spring Data JPA
Esempi
CrudRepository
public interface PersonRepository
extends JpaRepository,
PersonFragment {
...
}
Repository
JpaRepository
PagingAndSortingRepository
public class PersonRepository extends
Repository {
Person save(Person entity);
Optional findById(Person entity);
}
Repository Fragments
public interface PersonRepository
extends JpaRepository,
PersonFragment {
...
}
Metodi di query derivati
public interface PersonRepository extends CrudRepository {
List findByName(String name);
Person findByNameBySsn(String ssn);
Optional
findByNameBySsnIgnoreCase(String ssn);
Boolean existsBookByYearOfBirthBetween(
Integer start, Integer end);
}
Query definite dall'utente
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);
}
Interfacce API di MicroProfile
Tolleranza ai guasti
Le strutture di Fault tolerance sono molto importanti per prevenire guasti a cascata e creare architetture microserviziali affidabili. Gli sviluppatori di Spring utilizzano da molti anni i circuit-breaker per garantire la tolleranza ai guasti. . Tuttavia, Hystrix non è stato aggiornato da tempo, mentre la Fault Tolerance di MicroProfile si sta sviluppando attivamente ed ha già diversi anni di utilizzo in produzione. Pertanto, per aumentare l'affidabilità dei servizi in Quarkus, è consigliabile utilizzare le API di MicroProfile Fault Tolerance, i cui esempi di utilizzo sono riportati nella tabella 5. Maggiori informazioni si possono trovare nella guida di Quarkus. .
Tabella 5. Esempi di utilizzo delle API supportate da MicroProfile Fault Tolerance.
Funzioni di MicroProfile Fault Tolerance
Descrizione
Esempi
@Asynchronous
Esecuzione della logica in un thread separato
@Asynchronous
@Retry
public Future getSalutation() {
...
return future;
}
@Bulkhead
Limitazione del numero di richieste simultanee
@Bulkhead(5)
public void fiveConcurrent() {
makeRemoteCall(); //...
}
@CircuitBreaker
Gestione intelligente dei fallimenti e recupero dopo i guasti
@CircuitBreaker(delay=500 // millisecondi
failureRatio = .75,
requestVolumeThreshold = 20,
successThreshold = 5)
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
makeRemoteCall(); //...
}
@Fallback
Chiamata a logica alternativa in caso di errore
@Timeout(500) // millisecondi
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
makeRemoteCall(); //...
}
public String fallback() {
return "hello";
}
Ripetizione in caso di errore nella richiesta
@Retry(maxRetries=3)
public String getSalutation() {
makeRemoteCall(); //...
}
Tempo di attesa controllato in caso di errore
@Timeout(value = 500 ) // millisecondi
@Fallback(fallbackMethod = "fallback")
public String getSalutation() {
makeRemoteCall(); //...
}
Controllo dei servizi (Service Health)
Le piattaforme Kubernetes monitorano la salute dei container mediante servizi specializzati. Affinché la piattaforma sottostante possa monitorare i servizi, gli sviluppatori di Spring generalmente utilizzano HealthIndicator personalizzati e Spring Boot Actuator. In Quarkus, questo può essere fatto tramite MicroProfile Health, che per impostazione predefinita esegue il controllo della disponibilità (liveness check), ma può anche essere configurato per eseguire contemporaneamente il controllo della disponibilità e della prontezza (readiness). Gli esempi di utilizzo delle API MicroProfile Health supportate sono riportati nella tabella 6, mentre ulteriori informazioni sono disponibili nella guida di Quarkus. .
Tabella 6. Esempi di utilizzo delle API supportate da MicroProfile Health.
Funzioni di MicroProfile Health
Descrizione
Esempi
@Liveness
La piattaforma esegue il riavvio di applicazioni containerizzate non funzionanti
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
La piattaforma non invierà traffico alle applicazioni containerizzate in caso di non prontezza
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();
}
Metriche
Le applicazioni forniscono metriche sia in ottica operativa (per monitorare i KPI delle SLA), sia in ottica non operativa (KPI aziendali delle SLA). Gli sviluppatori Spring forniscono metriche tramite Spring Boot Actuator e Micrometer. D'altra parte, Quarkus utilizza MicroProfile Metrics per fornire metriche di base (JVM e sistema operativo), metriche del fornitore (Quarkus) e metriche delle applicazioni. MicroProfile Metrics richiede che l'implementazione supporti i formati di output JSON e OpenMetrics (Prometheus). Esempi di utilizzo dell'API MicroProfile Metrics sono riportati nella Tabella 7.
In Le MicroProfile Metrics vengono utilizzate per fornire metriche dell'applicazione. Maggiori dettagli possono essere trovati nella guida di Quarkus .
Tabella 7. Esempi di utilizzo delle API MicroProfile Metrics.
Funzionalità delle MicroProfile Metrics
Descrizione
Esempi
@Counted
Indica un contatore che conta il numero di chiamate all'oggetto annotato
@Counted(name = "fallbackCounter",
displayName = "Contatore di Fallback",
description = "Contatore di Fallback")
public String salutationFallback() {
return fallbackSalutation;
}
@ConcurrentGauge
Indica un gauge che conta il numero di chiamate parallele all'oggetto annotato
@ConcurrentGuage(
name = "fallbackConcurrentGauge",
displayName="Concurrent di Fallback",
description="Concurrent di Fallback")
public String salutationFallback() {
return fallbackSalutation;
}
@Gauge
Indica un gauge che misura il valore dell'oggetto annotato
@Metered(name = "FallbackGauge",
displayName="Gauge di Fallback",
description="Frequenza di Fallback")
public String salutationFallback() {
return fallbackSalutation;
}
@Metered
Indica un meter che tiene traccia della frequenza di chiamata dell'oggetto annotato
@Metered(name = "MeteredFallback",
displayName="Metered Fallback",
description="Frequenza di Fallback")
public String salutationFallback() {
return fallbackSalutation;
}
Annotazione che contiene informazioni sui metadati alla ricezione di richieste per la creazione o l'emissione di metriche
@Metric
@Metered(name = "MeteredFallback",
displayName="Metered Fallback",
description="Frequenza di Fallback")
public String salutationFallback() {
return fallbackSalutation;
}
Indica un timer che tiene traccia della durata dell'oggetto annotato
@Timed(name = "TimedFallback",
displayName="Timed Fallback",
description="Fallback delay")
public String salutationFallback() {
return fallbackSalutation;
}
Punti finali delle metriche (Metrics Endpoints)
Metriche delle applicazioni :8080/metrics/application
Metriche di base :8080/metrics/base
Metriche del fornitore :8080/metrics/vendor
Tutte le metriche :8080/metrics
Client REST MicroProfile
I microservizi spesso forniscono punti finali RESTful, per i quali sono necessari API client corrispondenti. Per utilizzare i punti finali RESTful, gli sviluppatori Spring di solito utilizzano RestTemplate. Quarkus, invece, offre per affrontare questa esigenza le interfacce API del Client REST di MicroProfile, dei cui esempi di utilizzo è fornita una tabella 8.
In L'uso dei punti finali RESTful avviene tramite il Client REST di MicroProfile. Maggiori informazioni e esempi su questo argomento sono disponibili nella guida di Quarkus .
Tabella 8. Esempi di utilizzo delle interfacce API del Client REST di MicroProfile.
Funzioni del Client REST di MicroProfile
Descrizione
Esempi
@RegisterRestClient
Registra un'interfaccia Java tipizzata come client REST
@RegisterRestClient
@Path("/")
public interface MyRestClient {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getSalutation();
}
@RestClient
Segna l'iniezione di un'istanza di un'interfaccia tipizzata REST client
@Autowired // o @Inject
@RestClient
MyRestClient restClient;
Invocazione
Chiama il punto finale REST
System.out.println(
restClient.getSalutation());
mp-rest/url
Imposta il punto finale REST
application.properties:
org.example.MyRestClient/mp-rest/url=
http://localhost:8081/myendpoint
Conclusioni
In questo blog, che sarà utile prima di tutto agli sviluppatori Spring, abbiamo brevemente esaminato come in Quarkus utilizzare le interfacce API di Spring insieme alle interfacce API di MicroProfile per sviluppare microservizi Java e poi compilarli in codice binario nativo, che consente di risparmiare centinaia di megabyte di memoria RAM e si avvia in pochi millisecondi.
Come già capito, ulteriori informazioni sul supporto delle interfacce API di Spring e MicroProfile, così come molte altre informazioni utili, possono essere trovate in .
Fonte: habr.com
