A equipe de portabilidade do Spring para GraalVM recentemente lançou seu primeiro grande lançamento, o Spring Native Beta. Junto com os criadores do GraalVM, eles foram capazes de corrigir muitos bugs no próprio compilador e na primavera. Agora o projeto tem suporte oficial, seu próprio ciclo de lançamento e você pode sentir isso.
O obstáculo mais importante ao portar código de JVM para binários é o problema de usar chips inerentes apenas em java - reflexão, trabalhar com o classpath, carregamento dinâmico de classes, etc.
De acordo com a documentação, as principais diferenças entre uma JVM regular e uma implementação nativa são as seguintes:
A análise estática de todo o aplicativo é realizada no momento da construção.
Os componentes não utilizados são removidos durante a montagem.
Reflexão, recursos e proxies dinâmicos só podem ser configurados com configurações adicionais.
No momento da construção, todos os componentes são fixados no Classpath.
Sem carregamento lento da classe: ao carregar, tudo o que vem nos executáveis será carregado na memória. Por exemplo, para que a chamada para Class.forName ("myClass") funcione corretamente, você precisa ter myClass no arquivo de configuração. Se nenhuma classe for encontrada no arquivo de configuração que é solicitado para carregar dinamicamente a classe, uma ClassNotFoundException será lançada
Parte do código será executado no momento da construção para vincular corretamente os componentes. Por exemplo, testes.
, , , - .
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")
@SpringBootApplication
public 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
.
Na verdade, executamos os comandos mvn spring-boot: build-image ou gradle bootBuildImage
- e a construção da imagem começará. Deve-se destacar que o coletor precisa de mais de 7 GB de memória, para que a montagem tenha sido concluída com sucesso. Na minha máquina, a montagem, juntamente com o download das imagens, não demorou mais que 5 minutos. Ao mesmo tempo, a imagem acabou ficando muito compacta, apenas 60 MB. O aplicativo foi iniciado em 0,022 segundos! Este é um resultado incrível. Considerando que cada vez mais empresas estão mudando para K8s e iniciando um aplicativo, assim como os recursos usados são muito importantes no mundo moderno, esta tecnologia permite ao Spring tornar-se o framework número um para todos os tipos de microsserviços, até mesmo para implementações FaaS, onde a velocidade fria é muito importante.