Как Quarkus объединяет MicroProfile и Spring

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

Как Quarkus объединяет MicroProfile и Spring

При разработке Java-микросервисов часто считается, что Eclipse MicroProfile и Spring Boot – это отдельные и независимые друг от друга API. По умолчанию, программисты, как правило, используют те API, к которым они уже привыкли, поскольку изучение новых фреймворков и runtime-компонентов требует много времени. Сегодня мы попробуем упростить освоение некоторых популярных MicroProfile API для Spring-разработчиков и покажем, как одновременно задействовать Spring API и новые полезные возможности Quarkus.

Если чуть подробнее, то сначала мы рассмотрим область применения и детали того, как 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

Чтобы не перегружать эту статью, мы рассмотрим здесь лишь высокоуровневые аспекты поддержки 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
Kubernetes

Service discovery
Eureka
DNS

Configuration
Spring Cloud Config
Config Maps / Secrets

Load balancing
Ribbon (на стороне клиента)
Service, Replication Controller(на стороне сервера)

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

В этой статье мы ссылаемся на пример проекта, где совместно используются API-интерфейсы Spring и MicroProfile и даже тот самый Java-класс. Код из этого примера можно скомпилировать и запустить из командной строки, подробнее см. файл README.md.

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

Dependency Injection

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
Примеры

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

Service

@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-разработчиков приятно порадует недавно появившаяся в Quarkus поддержка Spring Web API, в частности интерфейсов, отвечающих за 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 Data JPA

Пользователям 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 {
   ...
}

Repository
JpaRepository
PagingAndSortingRepository

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. Однако 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

Повтор при сбое запроса

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

Timeout

Контрольное время ожидания при сбое

@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 Health Guide.

Таблица 6. Примеры использования поддерживаемых API-интерфейсов MicroProfile Health.

Функции MicroProfile Health
Описание
Примеры

@Liveness

Платформа выполняет перезагрузку неисправных контейнеризованных приложений
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

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

Метрики

Приложения предоставляют метрики или в операционных целях (для контроля 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

Обозначает таймер, отслеживающий длительность аннотированного объекта

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

Конечные точки метрик (Metrics Endpoints)

Метрики приложений localhost:8080/metrics/application
Базовые метрики localhost:8080/metrics/base
Вендор-метрики localhost:8080/metrics/vendor
Все метрики localhost: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;

Invocation

Вызывает конечную точку 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

Добавить комментарий