Wie Quarkus MicroProfile und Spring vereint

Hallo zusammen, und hier ist der dritte Beitrag aus der Reihe über Quarkus!

Wie Quarkus MicroProfile und Spring vereint

Bei der Entwicklung von Java-Mikroservices wird oft angenommen, dass Eclipse MicroProfile und Spring Boot – das sind eigenständige und voneinander unabhängige APIs. Standardmäßig verwenden Programmierer in der Regel die APIs, an die sie bereits gewöhnt sind, da das Erlernen neuer Frameworks und Runtime-Komponenten viel Zeit in Anspruch nimmt. Heute werden wir versuchen, das Erlernen einiger beliebter MicroProfile-APIs für Spring-Entwickler zu erleichtern und zeigen, wie man gleichzeitig Spring APIs und neue nützliche Funktionen nutzen kann. unterstützt Quarkus die Verwendung des Advanced Message Queuing Protocol (.

Um es etwas genauer zu erläutern, werden wir zuerst den Anwendungsbereich und Details betrachten, wie Quarkus die Spring-API-Schnittstellen unterstützt, um Spring-Entwicklern zu zeigen, wie sie die MicroProfile-APIs in ihrem Alltag einsetzen können. Danach werden wir über die MicroProfile-APIs sprechen, die für Spring-Entwickler nützlich sind, wenn sie Mikroservices erstellen.

Warum gerade Quarkus? Erstens handelt es sich um Live-Coding, also um die automatische Neuladen aller Änderungen in MicroProfile-APIs, Spring-APIs und anderen Java-APIs, die mit einem einzigen Befehl ausgeführt werden: mvn quarkus:dev. Zweitens, das im unseren Beispiel Person-Dienst (der aus den API-Schnittstellen von Spring, MicroProfile und JPA in eine Binärdatei mit einem nativen Image von GraalVM kompiliert wird) benötigt nur 0,055 Sekunden zum Starten und belegt etwa 90 MB im Arbeitsspeicher (RSS) am Endpunkt der RESTful-Anwendung. Die eigentliche Kompilierung erfolgt ebenfalls mit einem einzigen Befehl: mvn package -Pnative.

Wir werden nicht in die Einzelheiten von MicroProfile eintauchen, sondern versuchen, Spring-Entwicklern zu helfen, zu verstehen, wie in Quarkus die Spring-API-Schnittstellen zusammen mit den MicroProfile-APIs verwendet werden können.

Container und Kubernetes

Um diesen Artikel nicht zu überladen, werden wir hier nur die hochrangigen Aspekte der Unterstützung betrachten, Kubernetesda dies wichtig zu verstehen ist. Quarkus wird als Java-Stack für Kubernetes positioniert, mit dem Ziel, den Speicherverbrauch und die Startzeit von Java-Anwendungen und -Diensten zu minimieren und somit die Dichte ihrer Platzierung auf einem Host zu erhöhen sowie die Gesamtkosten zu senken.

Quarkus unterstützt auch die Autogenerierung von Kubernetes-Ressourcen und bietet Handbuch zu Deployment auf Kubernetes- und Red Hat OpenShift-Plattformen. Darüber hinaus generiert Quarkus automatisch die Dockerfile.jvm (JVM-Packaging) und Dockerfile.native (native Binary-Packaging) Dateien, die zur Erstellung von Containern erforderlich sind.

Und schließlich, wenn wir Kubernetes als Ziel-Deployment-Umgebung betrachten, verwendet Quarkus keine Java-Frameworks, wenn eine ähnliche Funktionalität bereits auf der Ebene der Kubernetes-Plattform selbst implementiert ist. In Tabelle 1 finden Sie eine Karte zur funktionalen Übereinstimmung zwischen Kubernetes und den typischen Java-Frameworks, die von Spring-Entwicklern eingesetzt werden.

Tabelle 1. Karte zur funktionalen Übereinstimmung von Java-Frameworks und Kubernetes.

Funktionalität
Traditionelles Spring Boot
Kubernetes

Service-Entdeckung
Eureka
DNS

Konfiguration
Spring Cloud Config
Config Maps / Secrets

Lastverteilung
Ribbon (auf der Client-Seite)
Service, Replication Controller (auf der Server-Seite)

Kompilierung und Ausführung des Beispielcodes

In diesem Artikel verweisen wir auf das Beispielprojekt, in dem die APIs von Spring und MicroProfile gemeinsam verwendet werden, sowie die besagte Java-Klasse. Der Code aus diesem Beispiel kann aus der Kommandozeile kompiliert und ausgeführt werden, nähere Informationen finden Sie in der Datei README.md.

APIs des Spring Frameworks

Dependency Injection

Quarkus unterstützt eine Vielzahl von APIs für Contexts and Dependency Injection (CDI) und APIs für Spring Dependency Injection (Spring DI). Wenn Sie mit MicroProfile arbeiten, Java EE und Jakarta EE, dann sind Ihnen CDI bereits gut bekannt. Andererseits können Spring-Entwickler die Quarkus-Erweiterung für das Spring DI API nutzen, um die Kompatibilität mit Spring DI zu gewährleisten. Anwendungsbeispiele der unterstützten Spring DI APIs finden Sie in Tabelle 2.

Im In unserem Beispielprojekt werden sowohl CDI als auch Spring Dependency Injection verwendet. Weiterführende Informationen und Beispiele zu diesem Thema finden Sie im Quarkus-Handbuch mit dem Titel Spring DI Guide.

Tabelle 2. Beispiele für die Verwendung unterstützter Spring DI APIs.

Unterstützte Funktionen von Spring DI
Beispiele

Konstruktor-Injektion

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

Feldinjektion
Autowired
Wert

@Autowired
@RestClient
SalutationRestClient salutationRestClient;

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

Bean
@Configuration

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

Komponente

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

Service

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

   public String getPrefix() {
      return message;
   }
}

Web-Framework

MicroProfile-Benutzer werden erfreut sein zu erfahren, dass Quarkus JAX-RS, MicroProfile Rest Client, JSON-P und JSON-B als Hauptmodell für die Webprogrammierung unterstützt. Spring-Entwickler werden besonders erfreut sein über die kürzlich in Quarkus hinzugekommene Unterstützung für die Spring Web API, insbesondere für die Schnittstellen, die sich mit REST befassen. Ähnlich wie bei Spring DI ist das Hauptziel der Unterstützung der Spring Web API, dass Spring-Entwickler die Spring Web-Schnittstellen zusammen mit den MicroProfile-Schnittstellen nutzen können. Beispiele für die Verwendung der unterstützten Spring Web API sind in Tabelle 3 aufgeführt, und weitere Informationen und Beispiele zu diesem Thema finden Sie im Quarkus-Leitfaden mit dem Titel Spring Web Guide.

Tabelle 3. Beispiele für die Nutzung unterstützter Spring Web-Schnittstellen.

Unterstützte Funktionen von Spring Web
Beispiele

@RestController
@RequestMapping

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

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

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

Spring Data JPA

MicroProfile-Benutzer werden ebenfalls erfreut sein, dass Quarkus JPA mit Hibernate ORM unterstützt. Für Spring-Entwickler gibt es auch gute Nachrichten: Quarkus unterstützt gängige Annotations und Typen von Spring Data JPA. Beispiele für die Nutzung der unterstützten Spring Data JPA API sind in Tabelle 4 aufgeführt.
Im In unserem Beispielprojekt verwendete Schnittstellen von Spring Data JPA, und zusätzliche Informationen sind im Quarkus-Leitfaden unter dem Titel Spring Data JPA Guide.

Tabelle 4. Beispiele für die Nutzung unterstützter Spring Data JPA-Schnittstellen.

Unterstützte Funktionen von Spring Data JPA
Beispiele

CrudRepository

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

Repository
JpaRepository
PagingAndSortingRepository

public class PersonRepository extends 

    Repository {

    Person save(Person entity);

    Optional findById(Person entity);
}

Repository Fragmente

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

Abgeleitete Abfragemethoden

public interface PersonRepository extends CrudRepository {

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

    Boolean existsBookByYearOfBirthBetween(
            Integer start, Integer end);
}

Benutzerdefinierte Abfragen

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

Schnittstellen von MicroProfile

Fehlertoleranz (Fault tolerance)

Fault-Tolerance-Konstruktionen sind äußerst wichtig, um kaskadierende Ausfälle zu verhindern und zuverlässige Microservice-Architekturen zu schaffen. Spring-Entwickler nutzen seit vielen Jahren Circuit-Breaker zur Ausfallsicherheit. Hystrix. Allerdings wird Hystrix schon lange nicht mehr aktualisiert, während das MicroProfile Fault Tolerance aktiv weiterentwickelt wird und bereits mehrere Jahre Produktnutzung hinter sich hat. Daher wird empfohlen, die MicroProfile Fault Tolerance-API-Schnittstellen für die Verbesserung der Zuverlässigkeit von Diensten in Quarkus zu verwenden, deren Anwendungsbeispiele in Tabelle 5 aufgeführt sind. Weitere Informationen dazu finden Sie im Quarkus-Handbuch. Fault Tolerance Guide.

Tabelle 5. Beispiele für die Verwendung unterstützter MicroProfile Fault Tolerance-API-Schnittstellen.

Funktionen von MicroProfile Fault Tolerance
Beschreibung
Beispiele

@Asynchronous

Logik in einem separaten Thread ausführen

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

@Bulkhead

Begrenzung der Anzahl gleichzeitiger Anfragen

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

@CircuitBreaker

Intelligente Fehlerbehandlung und Wiederherstellung nach Fehlern

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

@Fallback

Aufruf alternativer Logik im Falle eines Fehlers

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

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

Retry

Wiederholen bei Anfragefehler

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

Timeout

Maximale Wartezeit bei einem Fehler

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

Service Health

Kubernetes-Plattformen überwachen die Integrität von Containern mithilfe spezieller Dienste. Damit die zugrunde liegende Plattform die Dienste überwachen kann, verwenden Spring-Entwickler normalerweise anpassbare HealthIndicator und Spring Boot Actuator. In Quarkus kann dies mit MicroProfile Health erfolgen, die standardmäßig einen Liveness-Check durchführen, aber auch so konfiguriert werden können, dass sie sowohl Liveness als auch Readiness (Bereitschaft) gleichzeitig überprüfen. Beispiele für die Verwendung der unterstützten MicroProfile Health-API sind in Tabelle 6 aufgeführt, und zusätzliche Informationen sind im Quarkus-Handbuch enthalten. Health Guide.

Tabelle 6. Beispiele für die Verwendung unterstützter MicroProfile Health-API-Schnittstellen.

Funktionen von MicroProfile Health
Beschreibung
Beispiele

@Liveness

Die Plattform führt einen Neustart fehlerhafter containerisierter Anwendungen durch.
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

Die Plattform wird keinen Verkehr an containerisierte Anwendungen senden, wenn diese nicht bereit sind.
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();  
}

Metriken

Anwendungen liefern Metriken entweder zu betrieblichen Zwecken (zur Überwachung von SLA-Leistungskennzahlen) oder zu nicht-betrieblichen Zwecken (Geschäftskennzahlen SLA). Spring-Entwickler liefern Metriken über Spring Boot Actuator und Micrometer. Quarkus hingegen verwendet MicroProfile Metrics zur Bereitstellung grundlegender Metriken (JVM und Betriebssystem), vendor-spezifischen Metriken (Quarkus) und Anwendungsmetriken. MicroProfile Metrics erfordert, dass die Implementierung Ausgabeformate in JSON und OpenMetrics (Prometheus) unterstützt. Beispiele für die Nutzung der MicroProfile Metrics API sind in Tabelle 7 aufgeführt.

Im In unserem Beispielprojekt MicroProfile Metrics werden zur Bereitstellung von Anwendungsmetriken verwendet. Weitere Informationen finden Sie im Quarkus-Handbuch. Metrik-Leitfaden.

Tabelle 7. Beispiele für die Nutzung von MicroProfile Metrics APIs.

Funktionen von MicroProfile Metrics
Beschreibung
Beispiele

@Counted

Kennzeichnet einen Counter-Zähler, der die Anzahl der Aufrufe des annotierten Objekts zählt.

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

@ConcurrentGauge

Kennzeichnet einen Gauge-Sensor, der die Anzahl der parallelen Aufrufe des annotierten Objekts zählt.

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

@Gauge

Kennzeichnet einen Gauge-Sensor, der den Wert des annotierten Objekts misst.

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

@Metered

Kennzeichnet einen Meter-Sensor, der die Häufigkeit der Aufrufe des annotierten Objekts verfolgt.

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

Metrik

Annotation, die Metadateninformationen enthält, wenn eine Anfrage zur Erstellung oder Produktion einer Metrik erfolgt.

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

Timed

Kennzeichnet einen Timer, der die Dauer des annotierten Objekts verfolgt.

@Timed(name = "TimedFallback",
   displayName="Timed Fallback",
   description="Fallback delay")
public String salutationFallback() {
   return fallbackSalutation;
}

Metrik-Endpunkte

Anwendungsmetriken localhost:8080/metrics/application
Basismetriken localhost:8080/metrics/base
Vendor-Metriken localhost:8080/metrics/vendor
Alle Metriken localhost:8080/metrics

REST-Client MicroProfile

Mikroservices bieten häufig RESTful-Endpunkte, für die entsprechende Client-APIs erforderlich sind. Um mit RESTful-Endpunkten zu arbeiten, verwenden Spring-Entwickler in der Regel RestTemplate. Quarkus bietet für diese Aufgabe die MicroProfile REST-Client-APIs, deren Verwendung in Tabelle 8 veranschaulicht wird.

Im In unserem Beispielprojekt Die Verwendung von RESTful-Endpunkten erfolgt über MicroProfile REST Client. Weitere Informationen und Beispiele finden Sie im Quarkus-Handbuch. REST-Client-Leitfaden.

Tabelle 8. Beispiele für die Verwendung der MicroProfile REST-Client-APIs.

Funktionen des MicroProfile REST Client
Beschreibung
Beispiele

@RegisterRestClient

Registriert eine typisierte Java-Schnittstelle als REST-Client

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

@RestClient

Kennzeichnet die Injektion einer Instanz der typisierten REST-Client-Schnittstelle

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

Aufruf

Ruft den REST-Endpunkt auf

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

mp-rest/url

Legt den REST-Endpunkt fest

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

Ergebnisse

In diesem Blog haben wir, der vor allem für Spring-Entwickler nützlich ist, kurz betrachtet, wie Quarkus die Spring-APIs zusammen mit den MicroProfile-APIs verwendet, um Java-Mikroservices zu entwickeln und sie dann in nativen Binärcode zu kompilieren, der Hunderte von Megabyte RAM spart und in wenigen Millisekunden startet.

Wie Sie bereits verstanden haben, finden Sie weitere Informationen zur Unterstützung der Spring- und MicroProfile-APIs sowie viele andere nützliche Informationen in den Quarkus-Leitfäden.

Quelle: habr.com

60GB SSD 8Gb DDR4