Русский
Русский
English
Статистика
Реклама

Релиз Spring Native Beta

Недавно команда, занимающаяся портированием Spring для GraalVM, выпустила первый крупный релиз - Spring Native Beta. Вместе с создателями GraalVM они смогли пофиксить множество багов как в самом компиляторе так и спринге. Теперь у проекта появилась официальная поддержка, свой цикл релизов и его можно щупать :)


Самым главным препятствием при переносе кода из JVM в бинарники является проблема использования фишек, присущих только java - рефлексия, работа с classpath, динамическая загрузка классов и т.д.

Согласно документации, ключевые различия между обычным JVM и нативной реализацией заключаются в следующем:

  • Статический анализ всего приложения выполняется во время сборки.

  • Неиспользуемые компоненты удаляются во время сборки.

  • Рефлексия, ресурсы и динамические прокси могут быть настроены только с помощью дополнительных конфигураций.

  • На время сборки фиксируются все компоненты в Classpath.

  • Нет ленивой загрузки класса: при загрузке все, что поставляется в исполняемых файлах, будет загружено в память. Например, чтобы вызов Class.forName ("myClass") отработал верно, нужно иметь myClass в файле конфигурации. Если в файле конфигурации не будет найден класс, который запрашивается для динамической загрузки класса, будет выбрано исключение ClassNotFoundException

  • Часть кода будет запущена во время сборки, чтобы правильно связать компоненты. Например, тесты.

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

В ходе исследований был создан новый компонент Spring AOT, который отвечает за все необходимые преобразования вашего кода в удобоваримый для Graal VM формат.

Spring AOT анализирует код и на основе него создает файлы конфигурации такие как native-image.properties, reflection-config.json, proxy-config.json или resource-config.json.

Так как Graal VM поддерживает первоначальную настройку через статические файлы, эти файлы помещаются при сборке в каталог META-INF/native-image.

Для каждого сборщика выпущен свой плагин, который активирует работу Spring AOT. Для maven это spring-aot-maven-plugin, соответственно для gradle - spring-aot-gradle-plugin.Для того, чтобы добавить gradle плагин в свой проект нужна всего одна строка:

plugins {id 'org.springframework.experimental.aot' version '0.9.0'}

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

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

Например, для случаев реализации компонентов с помощью WebClient можно использовать аннотацию из пакета org.springframework.nativex.hint, чтобы указать какой тип мы будем обрабатывать:

@TypeHint(types = Data.class, typeNames = "com.example.webclient.Data$SuperHero")@SpringBootApplicationpublic class WebClientApplication {// ...}

Здесь мы указываем, что будем сериализовать класс Data, в котором есть подкласс SuperHero. Во время сборки для нас заранее создадут клиент, который сможет работать с этим типом данных.

Так как graavlvm не поддерживает работу с динамическими прокси, то для поддержки работы с java.lang.reflect.Proxy создана аннотация @ProxyHint.

Применять ее можно, например, так:

@ProxyHint(types = {     org.hibernate.Session.class,     org.springframework.orm.jpa.EntityManagerProxy.class})

Если необходимо подтянуть какие-либо ресурсы в образ, то необходимо воспользоваться аннотацией@ResourceHint.Например, таким образом:

@ResourceHint(patterns = "com/mysql/cj/TlsSettings.properties")

Чтобы указать какие классы / пакеты должны быть инициализированы явно во время сборки или выполнения, нужно воспользоваться аннотацией @InitializationHint:

@InitializationHint(types = org.h2.util.Bits.class,    initTime = InitializationTime.BUILD)

Для того, чтобы компактно собрать все эти аннотации воедино создана аннотация @NativeHint:

@Repeatable(NativeHints.class)@Retention(RetentionPolicy.RUNTIME)public @interface NativeHint

Все вместе это будет выглядеть, например, вот так:

@NativeHint(    trigger = Driver.class,    options = "--enable-all-security-services",    types = @TypeHint(types = {       FailoverConnectionUrl.class,       FailoverDnsSrvConnectionUrl.class,       // ...    }), resources = {@ResourceHint(patterns = "com/mysql/cj/TlsSettings.properties"),@ResourceHint(patterns = "com.mysql.cj.LocalizedErrorMessages",                      isBundle = true)})

В качестве тригера, мы выбираем тот класс, присутствие которого в classpath должно вызвать построение конфигурации.

Все активные аннотации учитываются во время компиляции и преобразуются в конфигурацию Graal VM плагином Spring AOT.

Spring Native уже включена в релизный цикл, забрать шаблон можно прямо со start.spring.io. Так как поддержка JPA и прочих spring компонентов уже реализована, то собрать простое CRUD приложение можно сразу. Если необходимо указать дополнительные параметры Graal VM при сборке, их можно добавить с помощью переменной среды BP_NATIVE_IMAGE_BUILD_ARGUMENTS в плагине Spring AOT, если сборка идет через Buildpacks, или с помощью элемента конфигурации <buildArgs> в pom.xml, если вы собираете через плагин native-image-maven-plugin.

Собственно, выполняем команды mvn spring-boot: build-image или gradle bootBuildImage - и начнется сборка образа. Стоит отметить, что сборщику нужно более 7 Гб памяти, для того сборка завершилась успешно. На моей машине сборка, вместе с загрузкой образов заняла не более 5 минут. При этом образ получился очень компактным, всего 60 Мб. Стартовало приложение за 0.022 секунды! Это невероятный результат. Учитывая, что все большее количество компаний переходит на K8s и старт приложения, так же как и используемые ресурсы очень важны в современном мире, то данная технология позволяет Spring сделать фреймворком номер один для всех типов микросервисов, даже для реализаций FaaS, где очень важна скорость холодного старта.

Источник: habr.com
К списку статей
Опубликовано: 13.03.2021 20:20:43
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Java

Микросервисы

Spring

Jvm

Graalvm

Graal

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru