Информационный портал по безопасности » Программирование » Как Quarkus объединяет императивное и реактивное программирование

 

Как Quarkus объединяет императивное и реактивное программирование

Автор: admin от 20-03-2020, 14:25, посмотрело: 194

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



Как Quarkus объединяет императивное и реактивное программирование



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

Quarkus 1.0, релиза, который знаменует собой важную веху в развитии проекта и предлагает массу классных функций и возможностей (подробнее о них можно прочитать в анонсе).



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



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



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



Как Quarkus объединяет императивное и реактивное программирование

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



Начиная с версии 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 всё просто, но есть еще и БД, и файловые системы, и многое другое.



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




  • Эффективно использовать ресурсы на наиболее нагруженных направлениях программной системы;

  • Использовать более простой по стилю код в ее остальных частях.



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



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



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



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



    Как Quarkus объединяет императивное и реактивное программирование



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



    Как Quarkus объединяет императивное и реактивное программирование



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



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





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



    Полезные ресурсы







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



    Как пишут на сайте Quarkus.io, Quarkus – это 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-средах.





    Источник: Хабр / Интересные публикации

    Категория: Программирование

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

    Добавление комментария

    Имя:*
    E-Mail:
    Комментарий:
    • bowtiesmilelaughingblushsmileyrelaxedsmirk
      heart_eyeskissing_heartkissing_closed_eyesflushedrelievedsatisfiedgrin
      winkstuck_out_tongue_winking_eyestuck_out_tongue_closed_eyesgrinningkissingstuck_out_tonguesleeping
      worriedfrowninganguishedopen_mouthgrimacingconfusedhushed
      expressionlessunamusedsweat_smilesweatdisappointed_relievedwearypensive
      disappointedconfoundedfearfulcold_sweatperseverecrysob
      joyastonishedscreamtired_faceangryragetriumph
      sleepyyummasksunglassesdizzy_faceimpsmiling_imp
      neutral_faceno_mouthinnocent