Дорога в облака — способы разработки облачных приложений с использованием JVM в контейнерах, Quarkus и Spring Native
Хотите перенести Java-приложение на современную облачную платформу? Мы расскажем, как.
Эта статья посвящена трем методам облачно-ориентированной разработки, которые помогут повысить производительность ПО.
У облачных enterprise-проектов большие перспективы. Наши инженеры будут рады помочь с адаптацией и миграцией как монолитов, так и обширных микросервисных архитектур. На встрече с вашими разработчиками они предложат подходящее облачно-ориентированное решение для вашего проекта. Начните цифровую трансформацию прямо сейчас!
Подготовка
Предположим, что у вас уже имеется ПО на основе микросервисной архитектуры.
Первое, что вам понадобится вне зависимости от выбранного поставщика облачных услуг — это платформа для управления контейнеризированными компонентами или «среда оркестрации контейнеров». Рекомендуем использовать Kubernetes — переносимую платформу с открытым исходным кодом, которая обеспечивает масштабирование при использовании нескольких облачных сред. Это лидирующий на рынке продукт, который в 2020 году использовали 59 % Java-разработчиков из крупных организаций1.
Кроме того, вам необходим контроллер входящего трафика. Он связывает пользователя с конкретными экземплярами контейнеризированного приложения и выполняет функции балансировщика HTTP-нагрузки и прокси-сервера. Наши инженеры советуют использовать NGINX ingress controller с открытым исходным кодом, но вы можете выбрать альтернативный вариант2 , совместимый с Kubernetes.
Теперь все готово к созданию и облачному развертыванию микросервисных контейнеров. Поговорим об этом процессе с точки зрения как разработчиков, так и инженеров DevOps и рассмотрим три подхода: традиционный, с применением Quarkus и основанный на нативных образах.
JVM в Linux-контейнерах
В мире облачно-ориентированного ПО принято опираться на 4 важных методологии разработки: микросервисы, контейнеры, непрерывная интеграция/непрерывное развертывание (CI/CD) и DevOps3. Запуск Docker-контейнеров с облачными Java-приложениями в виртуальных машинах на Linux — простой подход, дающий мощную оптимизацию. Данный метод — в некотором роде наследник способа развертывания файлов WAR на веб-серверах до виртуализации на уровне ОС.
В качестве примера приведем конфигурацию Linux-контейнера: хостовая ОС гипервизора в облаке, гостевая ОС на ВМ в качестве главной ОС для Docker, Docker в гостевой ОС, предоставляющий среду выполнения контейнеров, и JVM внутри контейнера для выполнения байт-кода Java.
Axiom JDK рекомендует использовать Axiom JDK в качестве среды исполнения внутри контейнера. Axiom JDK отлично сочетается с большинством дистрибутивов Linux, включая легковесный Alpine. Такая сборка сократит статический и динамический объем используемой памяти, что в результате снизит затраты и увеличит общую прибыль.
Раньше такой подход сопровождался трудностями при управлении ресурсами контейнера. Если размер динамической памяти превышал ограничение по объему памяти контейнера, реализуемое с помощью контрольной группы (cgroups)), ОС могла остановить работу приложения. Сегодня эта проблема изучена и по большей части решена сообществом OpenJDK, поэтому шанс столкнуться с данной ситуацией составляет 1%.
MicroProfile и Quarkus
Еще один популярный подход к развертыванию в облаке — использование различных фреймворков с поддержкой MicroProfile, оптимизирующих применение Jakarta EE для микросервисов. Часть фреймворков включает собственные API, например, Micronaut. Другие, такие как Dropwizard, опираются на библиотеки для легковесной упаковки приложений. Некоторые из них разрабатываются крупными поставщиками JDK, например Helidon (Oracle) или Quarkus (Red Hat).
Рассмотрим подробнее проект Quarkus — фреймворк для Java для full-stack разработки, ориентированный на Kubernetes. Он адаптирован как для OpenJDK с виртуальной машиной HotSpot, так и для GraalVM в варианте нативной компиляции. Для создания микросервисов Quarkus использует библиотеки Eclipse MicroProfile и разнообразные инструменты: Apache Kafka, Camel, внедрение зависимостей, объектно-реляционное отображение Hibernate (аннотации JPA и JTA), RESTEasy (JAX-RS), Vert.x, Apache Camel и другие.
Другие преимущества проекта — поддержка плагинов Maven и Gradle (например, для запуска приложения Quarkus в режиме разработки на локальной или удаленной машине) и относительно короткое время запуска. Расширения Quarkus, встроенные в фреймворк или индивидуальные, упрощают разработку и развертывание микросервисов.
Тем не менее у подхода с применением MicroProfile есть ряд недостатков:
- Quarkus в значительной степени опирается на функции Kubernetes при выполнении задач в облаке (одна из них — управление трафиком). Компании, которые не использовали Kubernetes, столкнутся с трудностями, поскольку переход на него требует времени и сил;
- Внедрение этой технологии невозможно без отладки и тестирования. Например, если включить нативную компиляцию без установки расширения Quarkus, задача Gradle просто не выполнится, и при этом система не выведет сообщение об ошибке;
- Для Quarkus и других фреймворков создано меньше библиотек по сравнению с ближайшим конкурентом — Spring Boot.
Axiom NIK и Spring Native
Третий вариант основан на совмещении среды исполнения с целевым приложением. Представляем Native Image — прогрессивный облачно-ориентированный подход к разработке на Java, который объединяет функции JDK, заложенные в коде, и современные фичи. Для его создания подходит Axiom Native Image Kit — инструмент на базе GraalVM CE и технологий Axiom JDK. Axiom NIK преобразует байт-код Java в платформозависимый двоичный код для формирования нативных исполняемых файлов с малым размером и быстрым временем старта.
Axiom NIK поддерживает Alpine Linux с библиотекой musl и поэтому максимально снижает потребление ресурсов, экономит память и позволяет достичь рекордного времени запуска (до десятой доли секунды). Подробнее о преимуществах Axiom NIK — в статье, посвящённой этому инструменту.
Однако подход Native Image также связан с ограничениями. Иная модель оптимизации и предположение об ограниченности зависимостей в некоторых ситуациях приводят к нестандартному поведению приложений на Java. Следовательно, оптимизация такого рода подойдет не для любого ПО.
Решение данной проблемы заключается в применении Spring Framework и Spring Native — экспериментального набора инструментов и подходов для преобразования приложений Spring в нативные исполняемые файлы. Эти инструменты помогают преодолеть некоторые упомянутые ограничения нативных образов, а также обеспечивают нативное развертывание небольших контейнеров.
Подытоживая, сочетание этих инструментов дает продвинутый и в то же время простой и эффективный метод создания облачных приложений на Java.
У каждого из подходов — свои преимущества и недостатки, поэтому вам решать, какой из них оптимален для ваших приложений. Выберите один из предложенных вариантов или используйте свой. На какую бы платформу вы ни ориентировались, будь это классическая Java SE или GraalVM, профессионалы компании Axiom JDK с 20-летним опытом работы с Java окажут необходимую помощь.