Ki jan Quarkus konbine pwogram enperatif ak reyaktif

В этом году мы планируем всерьез развивать темы контейнеров, Cloud-Native Java и Kubernetes. Логичным продолжением этих тем будет рассказ о фреймворке Quarkus, уже рассмотренном на Хабре. Сегодняшняя статья посвящена не столько устройству «субатомной сверхбыстрой Java», сколько тем перспективам, которые Quarkus привносит в Enterprise.

Ki jan Quarkus konbine pwogram enperatif ak reyaktif

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

Сверхбыстрая субатомная Java вышла на новый уровень!

42 релиза, 8 месяцев работы сообщества и 177 потрясающих разработчиков – итогом всего это стал выпуск в ноябре 2019 года Karkus 1.0, релиза, который знаменует собой важную веху в развитии проекта и предлагает массу классных функций и возможностей (подробнее о них можно прочитать в anons).

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

Микросервисы, управляемые событиями архитектуры и sèvè-функции – все это сегодня, что называется, на подъеме. С недавних пор создание облачно-ориентированных архитектур стало гораздо проще и доступнее, однако проблемы остались – особенно у Java-разработчиков. Например, в случае serverless-функций и микросервисов есть острая необходимость в том, чтобы сократить время запуска, снизить расход памяти и таки сделать их разработку делом более удобным и приятным. Java в последние годы внесла несколько улучшений, вроде доработанного для контейнеров функционала ergonomics и проч. Однако добиться нормальной работы Java в контейнере по-прежнему непросто. Поэтому мы начнем с того, что рассмотрим некоторые из внутренних сложностей Java, которые особенно остро проявляются при разработке контейнерно-ориентированных Java-приложений.

Для начала обратимся к истории.

Ki jan Quarkus konbine pwogram enperatif ak reyaktif

Потоки и контейнеры

Начиная с версии 8u131, Java стала более-менее поддерживать контейнеры за счет улучшений в функционале ergonomics. В частности, теперь JVM знает, на скольких процессорных ядрах она выполняется, и может соответствующим образом настраивать пулы потоков – как правило, пулы fork/join. Безусловно, это замечательно, но, допустим, у нас есть традиционное веб-приложение, использующее HTTP-сервлеты и запускаемые в Tomcat, Jetty и проч. В результате это приложение выдаст каждому запросу отдельный поток и позволит ему блокировать этот поток при ожидании операций ввода-вывода, например, при обращении к БД, файлам или другим сервисам. То есть, размер такого приложения зависит не от количества доступных ядер, а от количества одновременных запросов. Кроме того, это означает, что квоты или лимиты в Kubernetes по количеству ядер тут не особо помогут, и дело в итоге закончится тротлингом.

Исчерпание памяти

Потоки – это память. И внутриконтейнерные ограничения на память отнюдь не панацея. Просто начните увеличивать количество приложений и потоков, и рано или поздно вы столкнетесь с критическим ростом частоты переключений и, как следствие, с деградацией производительности. Кроме того, если приложение использует традиционные микросервисные фреймворки или подключается к БД, или задействует кэширование, или как-то еще дополнительно расходует память, вам совершенно очевидно нужен инструмент, позволяющий заглянуть внутрь JVM и посмотреть, как она управляет памятью, и при этом не убить саму JVM (например, XX:+UseCGroupMemoryLimitForHeap). И даже несмотря на то, что, начиная с Java 9, JVM научилась воспринимать cgroups и соответствующим образом адаптироваться, резервирование и управление памятью остается довольно сложным делом.

Квоты и лимиты

В Java 11 появилась поддержка CPU-квот (вроде PreferContainerQuotaForCPUCount). Kubernetes тоже предлагает поддержку лимитов и квот. Да, всё это имеет смысл, но, если приложение опять выходит за рамки выделенной квоты, мы снова приходим к тому, что размер – как в случае с традиционными Java-приложениями – определяется по числу ядер и с выделением отдельного потока на каждый запрос, то есть толку от всего этого немного.
Кроме того, если использовать квоты и лимиты или функции горизонтального (scale-out) масштабирования платформы, лежащей в основе Kubernetes, проблема тоже не решается сама собой. Мы просто тратим больше ресурсов на решение исходной проблемы или в итоге приходим к перерасходу ресурсов. А если это высоконагруженная система в публичном общедоступном облаке, мы почти наверняка начинаем использовать больше ресурсов, чем это действительно нужно.

И что со всем этим делать?

Если по-простому, то использовать асинхронных и неблокирующие библиотеки ввода-вывода и фреймворки вроде Netty, Vert.x или Akka. Они гораздо лучше подходят для работы в контейнерах из-за своей реактивной природы. Благодаря неблокирующему вводу-выводу, один и тот же поток может обрабатывать сразу несколько одновременных запросов. Пока один запрос ждет результатов ввода-вывода, обрабатывающий его поток высвобождается и берется за другой запрос. А когда результаты ввода-вывода наконец-то поступают, обработка первого запроса продолжается. Чередуя обработку запросов в рамках одного и того же потока, можно сократить общее число потоков и снизить расход ресурсов на обработку запросов.

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

Как, и это всё?

Нет, есть еще кое-что. Реактивное программирование помогает лучше использовать ресурсы, но тоже имеет свою цену. В частности, код придется переписывать согласно принципам неблокируемости и избегать блокировки потоков ввода-вывода. А это совсем другая модель разработки и выполнения. И хотя здесь есть масса полезных библиотек, это все равно кардинальная смена привычного способа мышления.

Во-первых, вам надо научиться писать код, который выполняется асинхронно. Как только вы начинаете использовать неблокирующий ввод-вывод, вам требуется явно прописывать, что должно произойти при получении ответа на запрос. Просто блокировать и ждать больше не получится. Взамен вы можете передавать обратные вызовы, использовать реактивное программирование или continuation. Но и это еще не все: чтобы использовать неблокирующий ввод-вывод, вам нужны и неблокирующие сервера и клиенты, и желательно везде. В случае с HTTP всё просто, но есть еще и БД, и файловые системы, и многое другое.

И хотя тотальная сквозная реактивность дает максимум эффективности, такой сдвиг бывает трудно переварить на практике. Поэтому возможность сочетать реактивный и императивный код становится необходимым условием для того, чтобы:

  1. Эффективно использовать ресурсы на наиболее нагруженных направлениях программной системы;
  2. Использовать более простой по стилю код в ее остальных частях.

Представляем Quarkus

Собственно, в этом и есть суть Quarkus – объединить реактивную и императивную модели в рамках одной среды выполнения.

В основе Quarkus лежат Vert.x и Netty, поверх которых используется целый ряд реактивных фреймворков и расширений, призванных помочь разработчику. Quarkus предназначен для построения не только HTTP-микросервисов, но и управляемых событиями архитектур. Благодаря своей реактивной природе, он очень эффективно работает с системами обмена сообщениями (Apache Kafka, AMQP и т.д).

Вся хитрость в том, как использовать один и тот же реактивный движок как для императивного, так и для реактивного кода.

Ki jan Quarkus konbine pwogram enperatif ak reyaktif

Quarkus с этим блестяще справляется. Выбор между императивным и реактивным очевиден – использовать и для того, и для другого реактивное ядро. И с чем оно очень помогает, так это с быстрым неблокирующим кодом, который обрабатывает почти все, что проходит через поток цикла событий (event-loop thread, он же – IO thread). Но если у вас есть классические приложения REST или приложения на стороне клиента, у Quarkus наготове императивная модель программирования. Например, поддержка HTTP в Quarkus строится на использовании неблокирующего и реактивного движка (Eclipse Vert.x и Netty). Все HTTP-запросы, получаемые вашим приложением, вначале проходят через цикл событий (IO Thread), а затем отправляются той части кода, которая управляет запросами. В зависимости от точки назначения код управления запросами может вызываться в рамках отдельного потока (так называемый worker thread, применяется в случае сервлетов и Jax-RS) или же использовать исходный поток ввода-вывода (реактивный маршрут reactive route).

Ki jan Quarkus konbine pwogram enperatif ak reyaktif

Для коннекторов систем передачи сообщений используются неблокирующие клиенты, работающие поверх движка Vert.x. Поэтому вы можете эффективно отправлять, получать и обрабатывать сообщения от систем класса messaging middleware.

Sou sit la Quarkus.io собрано несколько хороших руководств, которые помогут начать работу с Quarkus:

Кроме того, мы подготовили онлайновые практические уроки для знакомства с различными аспектами реактивного программирования, причем для их прохождения достаточно всего лишь браузера, никакая IDE для этого не требуется, да и компьютер не обязателен. Найти эти уроки можно isit la.

Resous itil

10 видеоуроков по Quarkus, чтобы освоиться в теме

Как пишут на сайте Quarkus.io, Karkus - sa a Kubernetes-ориентированный Java-стек, заточенный под GraalVM и OpenJDK HotSpot и собранный из лучших Java-библиотек и стандартов.

Чтобы помочь вам разобраться в теме, мы отобрали 10 видеоуроков, где освещаются различные аспекты Quarkus и примеры его использования:

1. Представляем Quarkus: Java-фреймворк нового поколения для Kubernetes

Авторы: Томас Кворнстром (Thomas Qvarnstrom) и Джейсон Грин (Jason Greene)
Цель проекта Quarkus заключается в том, чтобы создать Java-платформу для Kubernetes и serverless-сред, а также объединить реактивную и императивную модели программирования в рамках единой среды выполнения, чтобы разработчики могли гибко варьировать подход при работе с широким спектром распределенных архитектур приложений. Узнайте больше из вводной лекции ниже.

2. Quarkus: сверхбыстрая субатомная Java

Автор: Блюр Саттер (Burr Sutter)
Видеоурок из интернет-лектория DevNation Live демонстрирует, как использовать Quarkus для оптимизации корпоративных Java-приложений, API, микросервисов и serverless-функций в среде Kubernetes/OpenShift, сделав их гораздо меньше, быстрее и масштабируемее.

3. Quarkus и GraalVM: разгоняем Hibernate до сверхскоростей и ужимаем до субатомных размеров

Автор: Сейн Гриноверо (Sanne Grinovero)
Из презентации вы узнаете, как появился Quarkus, как он работает и как позволяет сделать комплексные библиотеки, вроде Hibernate ORM, совместимыми с native-образами GraalVM.

4. Учимся разрабатывать serverless-приложения

Автор: Мартин Лютер (Marthen Luther)
В видео ниже показано, как создать простое Java-приложение с помощью Quarkus и развернуть его в качестве serverless-приложения на Knative.

5. Quarkus: кодируйте с удовольствием

Автор: Эдсон Янага (Edson Yanaga)
Видегайд по созданию вашего первого проекта Quarkus, позволяющий понять почему Quarkus завоевывает сердца разработчиков.

6. Java и контейнеры – каким будет их совместное будущее

Автор: Марк Литтл (Mark Little)
Эта презентация знакомит с историей Java и объясняет, почему Quarkus – это будущее Java.

7. Quarkus: сверхбыстрая субатомная Java

Автор: Дмитрис Адреандис (Dimitris Andreadis)
Обзор преимуществ Quarkus, получивших признание разработчиков: простота, сверхвысокие скорости, лучшие библиотеки и стандарты.

8. Quarkus и субатомные реактивные системы

Автор: Клемент Эскофьер (Clement Escoffier)
Благодаря интеграции с GraalVM Quarkus обеспечивает сверхбыстрый опыт разработки и субатомную среду исполнения. Автор говорит о реактивной стороне Quarkus и о том, как ей пользоваться при создании реактивных приложений и приложений с потоковой передачей данных.

9. Quarkus и быстрая разработка приложений в Eclipse MicroProfile

Автор: Джон Клинган (John Clingan)
Сочетая Eclipse MicroProfile и Quarkus, разработчики могут создавать полнофункциональные контейнерные приложения MicroProfile, которые запускаются за какие-то десятки миллисекунд. В видео подробно разбирается, как кодировать контейнерное приложение MicroProfile для развертывания на платформе Kubernetes.

10. Java, версия «Турбо»

Автор: Маркус Биль (Marcus Biel)
Автор показывает, как использовать Quarkus для создания супермаленьких и супербыстрых Java-контейнеров, позволяющих совершить настоящий прорыв, особенно в serverless-средах.



Sous: www.habr.com

Add nouvo kòmantè