Специалисты, занимающиеся плотно DevOps, контейнерами и бессерверными технологиями, часто пишут контейнеризованный код в легких контейнерах или FaaS на Python или JavaScript. Java просто слишком тяжел для начальной загрузки, чтобы использовать его в бессерверном фреймворке. Что касается работы с микросервисами, JavaScript или Python обеспечивают более быструю загрузку и более компактные контейнеры, благодаря чему оказываются эффективнее Java.
По мнению многих, Python и JavaScript – самые лучшие языки для создания облачно-ориентированных микросервисов.
Языку Java больше 20 лет, и во времена его зарождения мир был совершенно иным, нежели сейчас. С появлением JVM были решены огромные проблемы – мы получили возможность единожды написать код и запускать его на множестве платформ и операционных систем. Контейнеры позволяют упаковывать приложения, библиотеки и ресурсы операционной системы в отдельные емкости, и каждый такой контейнер может работать где угодно. Портируемость, которую обеспечивает JVM, теперь не так актуальна. В свое время мы были готовы нести дополнительные издержки для обеспечения портируемости, но теперь эти времена прошли. Теперь требуется быстрая работа с минимальными задержками и реактивные приложения, которые всегда будут доступны.
Компании, переходящие к использованию микросервисных архитектур, берут имеющиеся у них Spring-сервисы, написанные Java, связывают их в увесистые jar-архивы, добавляют JDK и запускают в контейнере, работающем на основе Linux. Такое решение работает, но вам приходится управляться с тяжелыми контейнерами размером по 500МБ, которые приводятся в состояние доступности за 10–30 секунд каждый, а это серьезная проблема. После миграции многие компании медленно переходят на использование Python, оставляя сервисы серверной части на Java, а, в конце концов, останавливаются на FaaS.
Бессерверные технологии и FaaS сегодня очень популярны, поскольку позволяют сосредоточиться на написании функций, не беспокоясь при этом об инфраструктуре. Как бы то ни было, все они работают в контейнерах, но облачный провайдер управляет их жизненным циклом. Самое приятное, что, спустя определенное время, провайдер полностью останавливает контейнер и возобновляет его работу только после следующего вызова, то есть, вы оплачиваете только время фактической работы. Первый вызов функции может продлиться несколько больше обычного, это и есть знаменитый холодный старт. Дело в том, что контейнеру необходима первичная загрузка. При использовании Python или JavaScript это не такая большая проблема, но в случае с Java первичная загрузка может занимать 10–15 секунд, а это уже приговор и одна из причин снижения популярности Java.
Сейчас актуален уже код, способный запуститься, выполнить задачу, а затем остановиться. Мы не хотим иметь дел со множеством потоков или долгоиграющими процессами, нам нужны короткоживущие процессы, которые могут загружаться очень быстро.
Сейчас стартап может писать функции и предоставлять их в облаке как услугу – благодаря использованию JavaScript – а также масштабировать их для поддержки миллионов пользователей, без необходимости управлять при этом инфраструктурой. Правда, существует еще и реальный мир за пределами Кремниевой долины: финансовые институты, государственное управление, розничная торговля и множество других отраслей, обслуживаемых при помощи миллионов строк на Java, переписывать которые слишком накладно. Поэтому приходится принять как данность тот факт, что в этих отраслях остается и дальше пользоваться тяжеловесными контейнерами.
Сила Quarkus заключается в том, что он использует GraalVM и предоставляет экосистему, поддерживающую AOT-компиляцию во время сборки. Таким образом, при помощи Java можно создавать нативные двоичные файлы. Благодаря Quarkus, GraalVM поступает в распоряжение Java-разработчиков.
Quarkus обеспечивает заблаговременную компиляцию для Java-приложений, и таким образом получается экосистема сверхзвуковой субатомной Java. Quarkus отличается сверхскоростной загрузкой – и Java возвращается в игру на поле облачно-ориентированной разработки. По-прежнему есть множество компаний, использующих Java+JPA внутри контейнера, но в такой конфигурации загрузка может занимать 15 секунд, а в случае Quarkus – 0,005!
При этом Вы используете ту же IDE и тот же инструментарий, к которым привыкли в мире Spring Boot. Для сборки вашего проекта используете Maven или Gradle. Проект можно запускать непосредственно в IDE и поверх нее, вам доступна горячая live-перезагрузка при любых изменениях, и перезапускать приложение при этом не требуется. Quarkus – это не Spring, поэтому, если вы используете Spring Boot, то придется выполнить миграцию Spring-специфичного кода. К счастью, в Quarkus предусмотрен уровень совместимости для внедрения зависимостей Spring, что сильно упрощает работу. Фреймворк Quarkus соответствует стандартам, что означает легкость в портировании и поддержке его кода.
Quarkus может использоваться в режиме разработки, этим он напоминает Spring Boot. С ним вы также можете упаковывать ваш проект в толстые jar. Это очень удобно для тестирования и отладки вашего кода, поскольку поддерживается live-перезагрузка, но для выхода в продакшен вам потребуется заблаговременная компиляция. Весь этот процесс показан на следующей схеме:
- Сначала собираете приложение в вашей любимой IDE, а затем можете запустить его в режиме разработчика при помощи: «mvnw compile quarkus:dev», как поступили бы с приложением Spring Boot. Также можете упаковать его в толстый jar.
- Как только закончите предыдущий этап, и результат вас устроит – вы готовы к созданию двоичного файла Java, просто запустите: «mvnw package -Pnative». На это потребуется некоторое время, поскольку в ходе заблаговременной компиляции будет создаваться нативный код!
Когда этот шаг будет завершен, у вас в распоряжении окажется сверхмалый и сверхбыстрый исполняемый файл, но работать он сможет лишь на вашей платформе/OS, то есть, он не портируется! Но и это нормально, поскольку мы можем поместить его в контейнер – и таким образом обеспечить портируемость.
Вот как это делается: ./mvnw package -Pnative -Dnative-image.docker-build=true4 – и мы вынимаем исполняемый файл из контейнера Docker, то есть, выполняем нативную сборку внутри контейнера и создаем двоичный файл. Этот прием может не сработать у вас на ноутбуке, если его операционная система отличается от целевой платформы, указанной в файле DockerFile, генерируемом Quarkus в ходе создания проекта.
- Затем, после того как у вас будет двоичный файл, просто создаем образ на основе файла docker. docker build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/quickstart.
- Наконец, приложение можно запустить в Docker или Kubernetes: docker run -i --rm -p 8080:8080 quarkus-quickstart/quickstart.
В Quarkus гораздо больше возможностей, чем в нативном коде Java:
- Унификация императивных и реактивных возможностей: позволяет комбинировать привычный императивный код с неблокирующим кодом, написанном в реактивном стиле.
- Разработчику приятно: унифицированная конфигурация, Zero config, live-перезагрузка в мгновение ока, оптимизированный обтекаемый код для 80% распространенных случаев и гибкий код для оставшихся 20% случаев, генерация нативных исполняемых файлов без суеты, live-кодинг.
- Поразительно быстрая загрузка, невероятно малая резидентная область памяти (да, речь не только о размере кучи!), что обеспечивает почти мгновенное вертикальное масштабирование и очень плотное использование памяти при оркестрации контейнеров на таких платформах как Kubernetes.
- Quarkus предлагает целостный, приятный в использовании full-stack фреймоврк, в несущие структуры которого внедрены первосортные библиотеки, которые вы знаете и любите.
- Поддерживаются библиотеки Hibernate, JPA, REST, JWT, т. д.
- Поддерживаются конфигурации, развернутые в Kubernetes и OpenShift.
- Открытая трассировка (open tracing) с использованием Jaeger.
- Поддержка Kotlin.
- Обмен сообщениями при помощи Kafka, Camel…
Заключение
С помощью Quarkus, проще говоря, можно запускать традиционные транзакционные сервисы JPA/JTA в супербыстрых легковесных контейнерах – как в облаке, так и на территории предприятия. Становится понятным, почему заслуживает внимания у многих фреймворк Quarkus, поддерживаемый Red Hat. Можно считать, что он изменит технологический ландшафт Java и обеспечит большим традиционным предприятиям реальную возможность миграции в облако.
Другими словами, Kubernetes + Knative + Quarkus меняют правила игры в облачно-ориентированной разработке и порадуют любого Java-разработчика.