- PVSM.RU - https://www.pvsm.ru -
Привет!
В наступившем новом году мы планируем всерьез развивать темы контейнеров, Cloud-Native Java [1] и Kubernetes [2]. Логичным продолжением этих тем на русском языке будет рассказ о фреймворке Quarkus [3], уже рассмотренном в хорошей статье на Хабре. Сегодняшняя статья посвящена не столько устройству "субатомной сверхбыстрой Java [4]", сколько тем перспективам, которые Quarkus привносит в Enterprise.
Java и JVM по-прежнему исключительно популярны, но при работе с бессерверными технологиями и облачно-ориентированными микросервисами Java и другие языки для JVM применяются все реже, так как занимают слишком много места в памяти и слишком медленно загружаются, из-за чего плохо подходят для использования с короткоживущими контейнерами. К счастью, в настоящее время эта ситуация начинает меняться благодаря Quarkus.
Введение
Чем плотнее я занимаюсь DevOps, контейнерами и бессерверными технологиями, тем чаще обнаруживаю, что пишу мой контейнеризованный код в легких контейнерах или FaaS [5] на Python или JavaScript. Java просто слишком тяжел для начальной загрузки, чтобы использовать его в бессерверном фреймворке. Что касается работы с микросервисами, JavaScript или Python обеспечивают более быструю загрузку и более компактные контейнеры, благодаря чему оказываются эффективнее Java.
Python и JavaScript – самые лучшие языки для создания облачно-ориентированных микросервисов
Языку Java больше 20 лет, и во времена его зарождения мир был совершенно иным, нежели сейчас. С появлением JVM были решены огромные проблемы – мы получили возможность единожды написать код и запускать его на множестве платформ и операционных систем. Контейнеры позволяют упаковывать приложения, библиотеки и ресурсы операционной системы в отдельные емкости, и каждый такой контейнер может работать где угодно. Портируемость, которую обеспечивает JVM, теперь не так актуальна. В свое время мы были готовы нести дополнительные издержки для обеспечения портируемости, но теперь эти времена прошли. Теперь требуется быстрая работа с минимальными задержками и реактивные приложения, которые всегда будут доступны. Контейнеры и инструменты для оркестрации контейнеров, например, Kubernetes [6], обеспечивают такие возможности независимо от языка программирования.
Компании, переходящие к использованию микросервисных архитектур, берут имеющиеся у них Spring [7]-сервисы, написанные Java, связывают их в увесистые jar-архивы, добавляют JDK и запускают в контейнере, работающем на основе Linux. Такое решение работает, но вам приходится управляться с тяжелыми контейнерами размером по 500МБ, которые приводятся в состояние доступности за 10-30 секунд каждый; это серьезная проблема. После миграции многие компании медленно переходят на использование Python, оставляя сервисы серверной части на Java, а, в конце концов, останавливаются на FaaS.
Бессерверные технологии и FaaS сегодня очень популярны, поскольку позволяют сосредоточиться на написании функций, не беспокоясь при этом об инфраструктуре. Как бы то ни было, все они работают в контейнерах, но облачный провайдер управляет их жизненным циклом. Самое приятное, что, спустя определенное время, провайдер полностью останавливает контейнер и возобновляет его работу только после следующего вызова, то есть, вы оплачиваете только время фактической работы. Первый вызов функции может продлиться несколько больше обычного, это и есть знаменитый холодный старт. Дело в том, что контейнеру необходима первичная загрузка. При использовании Python или JavaScript это не такая большая проблема, но в случае с Java первичная загрузка может занимать 10-15 секунд, а это уже приговор и одна из причин снижения популярности Java. Сейчас нам нужен код, способный запуститься, выполнить задачу, а затем остановиться. Мы не хотим иметь дел со множеством потоков или долгоиграющими процессами, нам нужны короткоживущие процессы, которые могут загружаться очень быстро.
Знакомство с Quarkus
Если вы читаете технические блоги или следите за новостями, то, возможно, полагаете, что бессерверная парадигма [8] захватывает мир, и все воспринимают ее с крайним энтузиазмом. Сейчас стартап может писать функции и предоставлять их в облаке как услугу – благодаря использованию JavaScript – а также масштабировать их для поддержки миллионов пользователей, без необходимости управлять при этом инфраструктурой. Правда, существует еще и реальный мир за пределами Кремниевой долины: финансовые институты, государственное управление, розничная торговля и множество других отраслей, обслуживаемых при помощи миллионов строк на Java, переписывать которые слишком накладно. Поэтому приходится принять как данность тот факт, что в этих отраслях остается и дальше пользоваться тяжеловесными контейнерами.
GraalVM [9] и, в частности, Substrate VM, сегодня открывают двери для славного и долгого будущего языка Java. GraalVM – это универсальная виртуальная машина для выполнения приложений, написанных на JavaScript, Python, Ruby, R и языках для JVM, в частности, Java, Scala или Kotlin. Самое классное, что GraalVM позволяет заранее (в AOT-режиме) компилировать программы в нативный исполняемый файл. Это означает, что вы можете компилировать ваш код Java непосредственно в машинно-специфичный код. Получаемая в результате программа не работает на Java HotSpot VM, но использует все необходимые компоненты, в частности, управление памятью, планирование потоков с иной реализации виртуальной машины, которая называется Substrate VM. Substrate VM написана на Java, и ее код компилируется в нативный исполняемый файл. Получаемая в результате программа быстрее запускается и, соответственно, дает более низкие издержки в использовании памяти по сравнению с Java VM. Это отлично, но, вероятно, вы думаете: заблаговременная компиляция? Она же противоречит базовой идее, ради которой создавалась JVM, то есть, использованию единожды написанного кода везде! Это же безумие!!! Однако, подумайте сами: теперь у нас есть контейнеры, а им не нужна JVM. Обычные контейнерные приложения, создаваемые при помощи Spring boot, имеют лишний уровень абстрагирования, который совершенно не нужен в мире, где есть Kubernetes. У вас есть приложение Java, работающее на JVM внутри контейнера, этот контейнер остается неизменным, поскольку в наши дни готовый продукт – это контейнер, а не приложение. Теперь мы упаковываем контейнеры, а не WAR-файлы. Поэтому, все издержки, связанные с использованием приложения на JVM внутри контейнера становятся бесполезными, и AOT становится весьма логичным решением, если вы собираетесь упаковывать ваши приложения в контейнеры.
Правда, AOT-компиляция серьезно ограничивает динамические возможности Java (загрузка классов во время исполнения, рефлексия, прокси, т.д.). На практике это означает, что 90% экосистемы Java без изменений работать не будет. Соответственно, экосистема Java должна адаптироваться. Есть и хорошие новости: большинство из этого можно сделать во время сборки!
В этом и заключается сила Quarkus. Он использует GraalVM и предоставляет экосистему, поддерживающую AOT-компиляцию во время сборки; таким образом, при помощи Java можно создавать нативные двоичные файлы. Благодаря Quarkus, GraalVM поступает в распоряжение Java-разработчиков.
Приступаем к работе с Quarkus
Как было объяснено выше, Quarkus обеспечивает заблаговременную компиляцию для Java-приложений, и таким образом получается экосистема сверхзвуковой субатомной Java; Quarkus отличается сверхскоростной загрузкой – и Java возвращается в игру на поле облачно-ориентированной разработки. Меня годами так не воодушевляла какая-либо новая технология – и я в этом не одинок [10].
Почитайте руководство для начинающих [11] – и убедитесь сами. По-прежнему есть множество компаний, использующих Java+JPA внутри контейнера, но в такой конфигурации загрузка может занимать 15 секунд, а в случае Quarkus – 0,005!
Статистика Quarkus
Вы используете ту же IDE и тот же инструментарий, к которым привыкли в мире Spring Boot. Для сборки вашего проекта используете Maven или Gradle. Проект можно запускать непосредственно в IDE и поверх нее, вам доступна горячая live-перезагрузка при любых изменениях, и перезапускать приложение при этом не требуется. Quarkus – это не Spring, поэтому, если вы используете Spring Boot, то придется выполнить миграцию Spring-специфичного кода. К счастью, в Quarkus предусмотрен уровень совместимости для внедрения зависимостей Spring [12], что сильно упрощает работу. Фреймворк Quarkus соответствует стандартам, что означает легкость в портировании и поддержке его кода.
Процесс разработки Quarkus
Quarkus может использоваться в режиме разработки, этим он напоминает Spring Boot. С ним вы также можете упаковывать ваш проект в толстые jar. Это очень удобно для тестирования и отладки вашего кода, поскольку поддерживается live-перезагрузка; но для выхода в продакшен вам потребуется заблаговременная компиляция. Весь этот процесс показан на следующей схеме:
mvnw compile quarkus:dev
”, как поступили бы с приложением Spring Boot. Также можете упаковать его в толстый jar.mvnw package -Pnative
”. На это потребуется некоторое время, поскольку в ходе заблаговременной компиляции будет создаваться нативный код! Когда этот шаг будет завершен, у вас в распоряжении окажется сверхмалый и сверхбыстрый исполняемый файл, но работать он сможет лишь на вашей платформе/OS, то есть, он не портируется! Но и это нормально, поскольку мы можем поместить его в контейнер – и таким образом обеспечить портируемость. Вот как это делается: ./mvnw package -Pnative -Dnative-image.docker-build=true
4 – и мы вынимаем исполняемый файл из контейнера Docker, то есть, выполняем нативную сборку внутри контейнера и создаем двоичный файл. Этот прием может не сработать у вас на ноутбуке, если его операционная система отличается от целевой платформы, указанной в файле DockerFile
, генерируемом Quarkus в ходе создания проекта.docker build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/quickstart
.docker run -i --rm -p 8080:8080 quarkus-quickstart/quickstart
Возможности Quarkus
В Quarkus гораздо больше возможностей, чем в нативном коде Java.
Экосистема Quarkus
Короче говоря, теперь можно запускать традиционные транзакционные сервисы JPA/JTA в супербыстрых легковесных контейнерах – как в облаке, так и на территории предприятия.
Пример Quarkus
В этом разделе давайте в упрощенном виде рассмотрим руководство для начинающих [11], чтобы составить впечатление о мощи Quarkus.
Простейший способ создать новый проект Quarkus – открыть окно командной строки и выполнить в нем следующую команду:
mvn io.quarkus:quarkus-maven-plugin:0.12.0:create
-DprojectGroupId=org.acme
-DprojectArtifactId=getting-started
-DclassName="org.acme.quickstart.GreetingResource"
-Dpath="/hello"
Таким образом генерируется проект Maven с GreetingResuce, предоставляющий конечную точку /hello. Также генерируются докерные образы Dockerfile для нативных файлов и jvm (традиционные образы в виде толстых jar). Код получается очень чистым и простым:
@Path("/hello")
public class GreetingResource { @GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "hello";
}
}
Для запуска приложения используйте: ./mvnw compile quarkus:dev
Приложение упаковывается при помощи ./mvnw package. В результате получается 2 jar-файла:
Запустить приложение можно с помощью: java -jar target/getting-started-1.0-SNAPSHOT-runner.jar
Затем нужно скачать и установить GraalVM и задать переменную окружения GRAALVM_HOME
.
Теперь можно создать нативный исполняемый файл при помощи: ./mvnw package -Pnative -Dnative-image.docker-build=true
.
Вот как создается образ Docker: docker build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/quickstart
.
Теперь его можно запустить при помощи любого движка оркестрации контейнеров, в случае, если вы используете minishift:
kubectl run quarkus-quickstart --image=quarkus-quickstart/quickstart:latest --port=8080 --image-pull-policy=IfNotPresent
kubectl expose deployment quarkus-quickstart --type=NodePort
Вот и все!; теперь у вас есть контейнер с REST-сервисом на Java, запускающийся за 0.004 секунд!
Вывод
Теперь понятно, почему меня так восхищает фреймворк Quarkus, поддерживаемый Red Hat. Я действительно считаю, что он изменит технологический ландшафт Java и обеспечит большим традиционным предприятиям реальную возможность миграции в облако.
Kubernetes + Knative + Quarkus меняют правила игры в облачно-ориентированной разработке и порадуют любого Java-разработчика.
В этом репозитории [19] – множество интересных примеров!
Автор: ph_piter
Источник [20]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/java/342171
Ссылки в тексте:
[1] Cloud-Native Java: https://www.piter.com/product_by_id/112863337
[2] Kubernetes: https://www.piter.com/product_by_id/125705747
[3] Quarkus: https://quarkus.io
[4] субатомной сверхбыстрой Java: https://habr.com/ru/company/haulmont/blog/443242/
[5] FaaS: https://ru.wikipedia.org/wiki/%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F_%D0%BA%D0%B0%D0%BA_%D1%83%D1%81%D0%BB%D1%83%D0%B3%D0%B0
[6] Kubernetes: https://kubernetes.io
[7] Spring: https://spring.io
[8] бессерверная парадигма: https://aws.amazon.com/ru/serverless/
[9] GraalVM: https://graalvm.org
[10] я в этом не одинок: https://dzone.com/articles/using-quarkus-to-run-java-apps-on-kubernetes-1
[11] руководство для начинающих: https://quarkus.io/guides/getting-started
[12] уровень совместимости для внедрения зависимостей Spring: https://quarkus.io/guides/spring-di
[13] Разработчику приятно: https://quarkus.io/vision/developer-joy
[14] См. подробнее: https://quarkus.io/vision/container-first
[15] Подробнее: https://quarkus.io/vision/standards
[16] OpenShift: https://www.openshift.com
[17] Kotlin: https://quarkus.io/guides/kotlin
[18] списком расширений: https://quarkus.io/extensions/
[19] репозитории: https://github.com/quarkusio/quarkus-quickstarts
[20] Источник: https://habr.com/ru/post/482968/?utm_source=habrahabr&utm_medium=rss&utm_campaign=482968
Нажмите здесь для печати.