Устойчивые микросервисы с Quarkus и Kotlin — Введение

Устойчивые микросервисы не всегда буквально необходимы для выживания, но представьте, что вы живете в районе, где водятся ядовитые змеи, и у вас на заднем дворе много детекторов, предупреждающих вас о них. Детекторы взаимодействуют через Wifi и REST-интерфейс с вашим сервером — поэтому это взаимодействие должно быть действительно надежным.

Как бы вы написали код для микросервиса на стороне сервера?
Какие технологии и языки вы бы использовали?

В этой серии статей я покажу, как реализовать отказоустойчивые микросервисы с помощью Kotlin и Quarkus. Это первая часть серии, в которой дается краткое введение в технологии, которые мы будем использовать, и почему они являются хорошим выбором для реализации заявленного сценария.

Почему Kotlin?

Прежде всего, давайте посмотрим, почему мы можем извлечь выгоду из использования Kotlin в качестве основного языка. Kotlin получил свой первый официальный релиз 1.0 в 2016 году. Уже тогда он имел множество улучшений по сравнению с текущим состоянием Java на тот момент, таких как:

  • Встроенная защита от нулей
  • классы данных
  • Встроенная поддержка функционального программирования
  • Функции расширения
  • Интеллектуальные приведения

и это только некоторые из них. Вот небольшой пример использования Kotlin:

data class User(
    // non null property
    val name: String, 
    // Int instead of int; no usage of primitives. 
    // But compiled to Javas int           
    val age: Int,  
    // nullable property              
    val description: String?     
)

val user = User(
    // named parameters
    name = "John Smith",  
    age = 30,
    description = null
)

// destructuring of data classes
val (name, age, description) = user    

val descriptionToPrint = description
        // null safe access to description with ?.
        ?.let { "the following description: $it" } 
        // fallback value for a null description 
        ?: "no description"    

// String builder
println("$name is $age old and $descriptionToPrint")    
// prints: John Smith is 30 old and no description
Вход в полноэкранный режим Выход из полноэкранного режима

Кроме того, существует множество других возможностей, с которыми можно поиграть. С момента выхода первых версий язык продолжал развиваться, добавлялись новые возможности. Наиболее важными из них являются Coroutines и Flow, а также более новые возможности языка, такие как

  • классы значений
  • контракты

или одно из новейших дополнений Context Receivers, которое все еще находится на стадии экспериментальной разработки. Кроме того, он отлично вписывается в мою личную экосистему, которая обусловлена следующими фактами:

  • Я в основном мобильный разработчик
  • У меня большой интерес к кросс-платформенным решениям
  • мне больше всего нравится платформа Android
  • Большинство приложений лучше работают с выделенным бэкендом для фронтенда, поэтому я пишу и их.

Kotlin предоставляет все необходимое для этого.

В родном мире Kotlin получил широкое распространение после того, как Google объявил, что он станет первоклассным гражданином для разработки под Android, а затем и ведущим языком, в основном заменив Java в этой области.

Совсем недавно Kotlin также представил решение для кросс-платформенной разработки в Kotlin Multiplatform, которое позволило запускать один и тот же код на Android, iOS, Web и Desktop.

Поскольку Java все еще сильна в области разработки бэкенда, многие используемые там фреймворки либо могут быть использованы с Kotlin, либо имеют дополнительную поддержку уникальных возможностей Kotlin. Такими фреймворками, например, являются Quarkus, Spring Boot или Micronaut. Также разработчикам доступны уже готовые фреймворки, которые являются родными для Kotlin, например Ktor.

Почему именно Quarkus?

Давайте подробнее рассмотрим Quarkus и почему он может помочь нам выполнить наши требования. Что такое Quarkus? Это простой подход к созданию масштабируемого бэкенда на уровне предприятия.

Вообще говоря, это облачный нативный Java-стек, который построен с использованием многих зрелых и хорошо известных (с открытым исходным кодом) Java-библиотек, фреймворков и стандартов. Поэтому вместо того, чтобы изучать все новое, мы можем использовать, например, Vert.x, Camel, Hibernate и RESTEasy. В случае стандартов мы можем найти MicroProfile и избранные спецификации Jakarta EE. Инъекция зависимостей использует хорошо известный CDI. Что касается аннотаций, то при определении конечных точек REST мы можем использовать аннотации JAX-RS. С одной стороны, аннотации JPA могут быть использованы для отображения постоянных сущностей. С другой стороны, аннотации JTA используются для объявления границ транзакций в Hibernate. И последнее, но не менее важное — это SmallRye для настройки, защиты и мониторинга нашего приложения.

Говорят, что это

сверхзвуковая субатомная Java

Что за Java?!

Вместо только Java, он также хорошо работает с GraalVM и Kotlin YAY!

Позже мы подробнее рассмотрим, как это сделать.

В чем идея Quarkus?

Идея Quarkus заключается в оптимизации Java для облачных нативных сред.

Это достигается за счет нескольких оптимизаций во время сборки, неудачного намерения запуска и того факта, что под ним лежит Vert.x.

Звучит неплохо при запуске приложений в контейнерах!

Что делает Quarkus для оптимизации времени сборки? Во время сборки Quarkus удаляет все ненужное. Кроме того, инъекции зависимостей анализируются и уже инжектируются во время компиляции — так что можно сказать, что это жестко подключено.

Благодаря намерению быстрого запуска, Quarkus реализует очень быстрое время запуска, что идеально подходит для облачных сред: при масштабировании для запуска большего количества контейнеров или в сценарии восстановления для перезапуска контейнеров.

Кроме того, поскольку Quarkus имеет под собой Vert.x, он опирается на модель реактора, поэтому может легко обрабатывать большое количество запросов. Это хорошо для нас, когда поступает много запросов.

С моей точки зрения

Quarkus предлагает горячую перезагрузку, которая не является очевидной в мире Java, но ощущается как современная технология. Я обычно использую его ежедневно, поэтому он очень важен для меня.

Quarkus имеет активное и поддерживающее сообщество, где мы можем вносить свой вклад и быстро обмениваться информацией. У вас есть запрос, например, на улучшение поддержки Kotlin? Просто поговорите с ними и, в лучшем случае, предложите PR самостоятельно. Вас обязательно услышат.

Имея большой опыт написания бэкендов на Java, Quarkus позволяет мне чувствовать себя как дома благодаря их соответствию спецификациям JEE (Annotations, Extensions, Frameworks, Libraries …) и особенно RESTeasy. Это даже не приводит к каким-либо недостаткам в производительности, так как все отображается в Quarkus cloud native во время сборки. Но в отличие от подхода JEE к обработке аннотаций во время выполнения, Quarkus выполняет эти операции во время сборки, что значительно повышает производительность приложения Quarkus.
Если этого недостаточно, вы можете скомпилировать Quarkus в нативный двоичный файл, что еще больше повышает производительность.

Императивный и реактивный

Quarkus дает нам свободу реализовать наше приложение в императивном стиле, который хорошо известен по JEE, но он также позволяет использовать более реактивный подход — используя возможности Kotlin Flows.

Императив (конечная точка REST)

@Path("greeting")
class GreetingEndpoint(
    private val greetingService: GreetingService
) {
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    fun greeting(@QueryParam("username") username: String?) = 
            greetingService.greet(username)
}
Вход в полноэкранный режим Выход из полноэкранного режима

Реактивный (события, посылаемые сервером)

@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
@RestSseElementType(MediaType.TEXT_PLAIN)
fun stream(): Flow<String> = flow {
        emitAll(channel.asFlow())
    }
Вход в полноэкранный режим Выход из полноэкранного режима

Простая настройка проекта с помощью генерации кода

Приступить к работе довольно просто, посетив сайт https://code.quarkus.io/. В качестве первого шага начните поиск Kotlin и установите флажок related.

После этого найдите RESTeasy-reactive и убедитесь, что флажок related также установлен.

Отлично! Наше приложение готово к загрузке.

Теперь мы можем приступить к написанию нашей первой конечной точки.

@Path("greeting")
class GreetingEndpoint(
    private val greetingService: GreetingService
) {
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    fun greeting(@QueryParam("username") username: String?) = 
            greetingService.greet(username)
}
Вход в полноэкранный режим Выход из полноэкранного режима

Приведенный выше пример кода дает нам конечную точку GET с параметром запроса имени пользователя и создает ответное сообщение приветствия с медиатипом TEXT_PLAIN.

Чтобы запустить его, просто выполните

quarkus dev
Войти в полноэкранный режим Выйти из полноэкранного режима

в командной строке. Для проверки ответа используйте rest-клиент, например postman.

Но как сделать это устойчивым?

Мы рассмотрим это в части 2, выделив шаблоны проектирования отказоустойчивости, которые делают больше всего для сокращения времени восстановления и времени простоя — следите за новостями.

А пока, если вы хотите попробовать мой пример приветствия, приведенный выше, вы можете найти его на Github.

Оцените статью
Procodings.ru
Добавить комментарий