Як Quarkus об'єднує MicroProfile та Spring

Всім привіт, і з вами третій пост із серії про Quarkus!

Як Quarkus об'єднує MicroProfile та Spring

При розробці Java-мікросервісів часто вважається, що Мікропрофіль Eclipse и Весняний черевик – це окремі та незалежні один від одного API. За замовчуванням, програмісти зазвичай використовують ті API, до яких вони вже звикли, оскільки вивчення нових фреймворків і runtime-компонентів вимагає багато часу. Сьогодні ми спробуємо спростити освоєння деяких популярних MicroProfile API для Spring-розробників і покажемо, як одночасно задіяти Spring API та нові корисні можливості Кваркус.

Якщо трохи докладніше, то спочатку ми розглянемо сферу застосування та деталі того, як Quarkus підтримує API-інтерфейси Spring, щоб показати Spring-розробникам, як можна застосовувати MicroProfile API у своїй повсякденній роботі. Потім ми розповімо про MicroProfile API, які стануть у нагоді Spring-розробникам при створенні мікросервісів.

Чому саме Quarkus? По-перше, це кодування наживо (live coding), тобто автоматичне перезавантаження будь-яких змін у MicroProfile API, Spring API та інших Java API, яке виконується лише однією командою: mvn quarkus:dev. По-друге, розглядається в нашому прикладі сервіс Person (він компілюється з API-інтерфейсів Spring, MicroProfile та JPA в двійковий файл з використанням нативного образу GraalVM) запускається всього за 0.055 секунди і займає близько 90 МБ в оперативній пам'яті (RSS) на кінцевій точці програми RESTful. Причому сама його компіляція виконується лише однією командою: mvn package -Pnative.

Ми не будемо заглиблюватися в подробиці MicroProfile, а лише намагатимемося допомогти Spring-розробникам зрозуміти, як у Quarkus можна використовувати API-інтерфейси Spring разом з API-інтерфейсами MicroProfile.

Контейнери та Kubernetes

Щоб не перевантажувати цю статтю, ми розглянемо лише високорівневі аспекти підтримки. Кубернетесоскільки це важливо розуміти. Quarkus позиціонується як Java-стек для Kubernetes, він покликаний мінімізувати витрати пам'яті та час запуску Java-додатків та сервісів, і, як наслідок, підвищити щільність їх розміщення на хості та знизити загальні витрати.

Quarkus також підтримує автогенерацію ресурсів Kubernetes та пропонує керівництва з розгортання на платформах Kubernetes та Red Hat OpenShift. Крім того, Quarkus автоматично генерує файли Dockerfile.jvm (JVM packaging) та Dockerfile.native (native binary packaging), необхідні створення контейнерів.

І нарешті, орієнтуючись на Kubernetes як на цільове середовище розгортання, Quarkus не використовує Java-фреймворки у випадках, коли аналогічний функціонал реалізований лише на рівні самої платформи Kubernetes. У таблиці 1 наводиться карта функціональної відповідності Kubernetes та типових Java-фреймворків, що застосовуються Spring-розробниками.

Таблиця 1. Карта функціональної відповідності Java-фреймворків та Kubernetes.

Функціонал
Традиційний Spring Boot
Кубернетес

Відкриття служби
Еврика
DNS

конфігурація
Spring Cloud Config
Config Maps / Secrets

Балансування навантаження
Ribbon (на стороні клієнта)
Service, Replication Controller (на стороні сервера)

Компіляція та запуск коду з прикладу

У цій статті ми посилаємось на приклад проекту, де спільно використовуються API-інтерфейси Spring і MicroProfile і навіть цей Java-клас. Код цього прикладу можна скомпілювати і запустити з командного рядка, докладніше див. файл README.md.

API-інтерфейси Spring Framework

Ін'єкційна залежність

Quarkus підтримує цілий ряд API-інтерфейсів Contexts and Dependency Injection (CDI) та API-інтерфейсів Spring Dependency Injection (Spring DI). Якщо ви працюєте з MicroProfile, Java EE та Jakarta EEвже добре знайомі з CDI. З іншого боку, Spring-розробники можуть використовувати Quarkus Extension for Spring DI API для забезпечення сумісності із Spring DI. Приклади використання Spring DI API, що підтримуються, наводяться в таблиці 2.

В проект з нашого прикладу використовується як CDI, так і Spring Dependency Injection. Додаткові відомості та приклади на цю тему можна знайти у посібнику Quarkus, яке називається Spring DI Guide.

Таблиця 2. Приклади використання підтримуваних інтерфейсів API Spring DI.

Функції Spring DI, що підтримуються
Приклади

Інжекція конструктора

public PersonSpringController(
   PersonSpringRepository personRepository,  // injected      
   PersonSpringMPService personService) {    // injected
      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;
   }
}

Веб-фреймворк

Користувачам MicroProfile сподобається, що Quarkus підтримує JAX-RS, MicroProfile Rest Client, JSON-P та JSON-B як основну модель веб-програмування. Spring-розробників приємно порадує підтримка Spring Web API, що недавно з'явилася в Quarkus, зокрема інтерфейсів, що відповідають за REST. За аналогією зі Spring DI, головна мета підтримки Spring Web API полягає в тому, щоб Spring-розробники могли використовувати API-інтерфейси Spring Web разом з API-інтерфейсами MicroProfile. Приклади використання Spring Web API, що підтримуються, наводяться в таблиці 3, а додаткові відомості та приклади на цю тему можна знайти в посібнику Quarkus, яке називається Spring Web Guide.

Таблиця 3. Приклади використання підтримуваних інтерфейсів API Spring Web.

Функції Spring Web, що підтримуються
Приклади

@RestController
@RequestMapping

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

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

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

Spring DataJPA

Користувачам MicroProfile також сподобається, що Quarkus підтримує JPA з використанням Hibernate ORM. Для Spring-розробників також є хороша новина: Quarkus підтримує загальноприйняті інструкції та типи Spring Data JPA. Приклади використання Spring Data JPA API, що підтримуються, наводяться в таблиці 4.
В проект з нашого прикладу використовуються API-інтерфейси Spring Data JPA, а додаткова інформація доступна у посібнику Quarkus під назвою Spring Data JPA Guide.

Таблиця 4. Приклади використання підтримуваних API-інтерфейсів Spring Data JPA.

Функції Spring Data JPA, що підтримуються
Приклади

CrudRepository

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

Сховище
JpaRepository
Репозиторій PagingAndSorting

public class PersonRepository extends 

    Repository {

    Person save(Person entity);

    Optional findById(Person entity);
}

Repository Fragments

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

Derived query methods

public interface PersonRepository extends CrudRepository {

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

    Boolean existsBookByYearOfBirthBetween(
            Integer start, Integer end);
}

User-defined queries

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-інтерфейси MicroProfile

Відмовостійкість (Fault tolerance)

Конструкції Fault tolerance дуже важливі для запобігання каскадним відмовам та створенню надійних мікросервісних архітектур. Spring-розробники вже багато років використовують для стійкості до відмови circuit-breaker'и Гістрікс. Однак Hystrix давно не оновлювався, а ось MicroProfile'євський Fault Tolerance зараз активно розвивається і має за плечима вже кілька років продакшн-використання. Тому для підвищення надійності сервісів у Quarkus рекомендується застосовувати API-інтерфейси MicroProfile Fault Tolerance, приклади використання яких наведені в таблиці 5. Додаткові відомості про це можна знайти у посібнику Quarkus Fault Tolerance Guide.

Таблиця 5. Приклади використання підтримуваних інтерфейсів API MicroProfile Fault Tolerance.

Функції MicroProfile Fault Tolerance
Опис
Приклади

@Asynchronous

Виконання логіки в окремому потоці

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

@Bulkhead

Обмеження кількості одночасних запитів

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

@CircuitBreaker

Розумна обробка збоїв та відновлення після збоїв

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

@Fallback

Виклик альтернативної логіки у разі збою

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

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

Повторити

Повторення при збої запиту

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

Тайм-аут

Контрольний час очікування під час збою

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

Перевірка сервісів (Service Health)

Kubernetes-платформи відстежують справність контейнерів за допомогою спеціальних сервісів. Щоб нижчележача платформа могла моніторити сервіси, Spring-розробники зазвичай використовують HealthIndicator і Spring Boot Actuator, що настроюються. У Quarkus це можна зробити за допомогою MicroProfile Health, які за умовчанням виконують перевірку працездатності (liveness check), але можуть бути налаштовані на одночасну перевірку liveness і readiness (готовності). Приклади використання MicroProfile Health API, що підтримуються, наведені в таблиці 6, а додаткова інформація представлена ​​в посібнику Quarkus Керівництво з охорони здоров’я.

Таблиця 6. Приклади використання підтримуваних інтерфейсів API MicroProfile Health.

Функції MicroProfile Health
Опис
Приклади

@Liveness

Платформа виконує перезавантаження несправних контейнеризованих додатків
Кінцева точка:
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

Платформа не буде відправляти трафік на контейнеризованих додатків у разі його неготовності
Кінцева точка:
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();  
}

Метрики

Додатки надають метрики або в операційних цілях (для контролю SLA-показників продуктивності), або неопераційних (бізнес-показники SLA). Spring-розробники надають метрики за допомогою Spring Boot Actuator та Micrometer. У свою чергу, Quarkus використовує MicroProfile Metrics для надання базових метрик (JVM та операційна система), вендор-метрик (Quarkus) та метрик додатків. MicroProfile Metrics вимагає, щоб реалізація підтримувала вихідні формати JSON та OpenMetrics (Prometheus). Приклади використання MicroProfile Metrics API наведено у таблиці 7.

В проект з нашого прикладу MicroProfile Metrics використовуються для надання метрик програми. Для отримання додаткових відомостей див. посібник Quarkus Metrics Guide.

Таблиця 7. Приклади використання інтерфейсів API MicroProfile Metrics.

Функції MicroProfile Metrics
Опис
Приклади

@Counted

Позначає counter-лічильник, який підраховує кількість викликів анотованого об'єкта

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

@ConcurrentGauge

Позначає gauge-датчик, який підраховує кількість паралельних викликів анотованого об'єкта

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

@Gauge

Позначає gauge-датчик, що вимірює значення анотованого об'єкта

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

@Metered

Позначає meter-датчик, який відстежує частоту виклику анотованого об'єкта

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

Metric

Анотація, що містить інформацію про метадані, при надходженні запиту на внесення або виробництво метрики

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

Приурочений

Позначає таймер, який відстежує тривалість анотованого об'єкта

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

Кінцеві точки метрик (Metrics Endpoints)

Метрики додатків локальний:8080/metrics/application
Базові метрики локальний:8080/metrics/base
Вендор-метрики локальний:8080/metrics/vendor
Усі метрики локальний:8080/metrics

Rest-клієнт MicroProfile

Мікросервіси часто пропонують кінцеві точки RESTful, для роботи з якими потрібні відповідні клієнтські API. Щоб використовувати кінцеві точки RESTful, Spring-розробники зазвичай застосовують RestTemplate. Quarkus пропонує для вирішення цього завдання API-інтерфейси MicroProfile Rest Client, приклади використання яких наводяться в таблиці 8.

В проект з нашого прикладу використання кінцевих точок RESTful виконується за допомогою MicroProfile Rest Client. Додаткові відомості та приклади на цю тему можна знайти у посібнику Quarkus Rest Client Guide.

Таблиця 8. Приклади використання інтерфейсів API MicroProfile Rest Client.

Функції MicroProfile Rest Client
Опис
Приклади

@RegisterRestClient

Реєструє типізований Java-інтерфейс як клієнт REST

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

@RestClient

Зазначає використання екземпляра типізованого інтерфейсу REST-клієнта

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

благання

Викликає кінцеву точку REST

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

mp-rest/url

Задає кінцеву точку REST

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

Підсумки

У цьому блозі, який в першу чергу стане в нагоді Spring-розробникам, ми коротко розглянули, як у Quarkus використовувати API-інтерфейси Spring разом API-інтерфейсами MicroProfile, щоб розробляти мікросервіси Java і потім компілювати їх у нативний двійковий код, який заощаджує сотні мегабайт оперативної пам'яті і запускається за лічені мілісекунди.

Як ви вже зрозуміли, додаткові відомості про підтримку API-інтерфейсів Spring і MicroProfile, а також багато іншої корисної інформації можна знайти в керівництві Quarkus.

Джерело: habr.com

Додати коментар або відгук