spring-boot
graalvm
Micronaut

Spring Boot ApplicationをMicronaut for Springでnative-imageにしてみる


はじめに

Spring Bootの起動速度のとにかく速めたいな、と思い Micronaut for Spring を試してみた結果です。

もし、間違っている部分があればご指摘していただけると嬉しいです。


結果

Spring Bootのアプリケーションを、native-imageするのはまだ早い。

でも、何か今後行けそうな夢が見れた。

ソースは全て下記リポジトリの micronaut-maven ブランチです。micronaut-gradleは、gradle用です。

https://github.com/h-r-k-matsumoto/spring-boot-sample


調査したこと


Spring Framwork 5.1: Support for Graal native image

Spring Frameworkは、5.1のwikiに下記のように書いています。


Support for Graal native image constraints (reflection, parameter names).


もしかして、何もせずともnativeimage作れる?と思いましたが、できませんでした。

GraalVMじゃなくて、Graal(JIT Compiler)にサポートした・・・という事なのかな。少なくとも、

https://jira.spring.io/browse/SPR-16991

にある通り、GraalVM側での対応も行って上で、さらにSpring Framework側の対応が必要という事なのでしょう。

ただ、下記のようにDIの設定を app.json のように書き出せば・・・動くのかもしれません。

https://github.com/dsyer/spring-boot-aot


Micronaut for Spring

https://github.com/micronaut-projects/micronaut-spring

https://micronaut-projects.github.io/micronaut-spring/latest/guide/index.html

簡単にいうと、Spring ApplicationをMicronaut Appkicationとして実行できるよ!というものです。

お?これはもしかしてSpring BootからMicronautへの移行なども考慮してスムーズに行えるのでは!?

と試してみました。


Micronaut for Spring:既存のSpring Bootアプリケーションを変更する

今回以前作成した簡単なSpring Bootアプリケーションを使いました。

https://github.com/h-r-k-matsumoto/spring-boot-sample


変更すること


依存関係の追加。

micronaut、micronaut-for-spring、graalvm関連のライブラリを追加する必要があります。

詳細は、下記をみてください。

https://github.com/h-r-k-matsumoto/spring-boot-sample/blob/micronaut-maven/pom.xml#L46-L105


fatJarの作り方の変更

spring-boot-maven-plugin で作成されたfatJarは対応されていません。

というよりも、 org.springframework.boot.loader.JarLauncher でしか読み込めない形式なので、一般的なjarにする必要があります。

maven-shade-pluginを使い、単純なjar形式に全てのクラスを含めます。

excludeしているのは、gradleでいうところの compileOnly がないため、dependencyでcompileで追加しつつ、jarに固める際に外しています。

https://github.com/h-r-k-matsumoto/spring-boot-sample/blob/micronaut-maven/pom.xml#L110-L130


pom.xml

            <plugin>

<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<excludes>
<exclude>com.oracle.substratevm:*</exclude>
<exclude>org.graalvm.truffle:*</exclude>
<exclude>org.graalvm.sdk:*</exclude>
<exclude>org.graalvm.compiler:*</exclude>
</excludes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>


AnnotationProcessorの追加

compile時にannotationを独自に解析する拡張を有効化します。

https://github.com/h-r-k-matsumoto/spring-boot-sample/blob/micronaut-maven/pom.xml#L132-L160


pom.xml

            <plugin>

<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject-java</artifactId>
<version>${micronaut.version}</version>
</path>
<path>
<groupId>io.micronaut.spring</groupId>
<artifactId>micronaut-spring-boot-annotation</artifactId>
<version>${micronaut.spring.version}</version>
</path>
<path>
<groupId>io.micronaut.spring</groupId>
<artifactId>micronaut-spring-web-annotation</artifactId>
<version>${micronaut.spring.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>


アプリケーションの起動

アプリケーションの起動方法を、  org.springframework.boot.SpringApplication#run ではなく、下記のように、 Micronaut#run に変更する必要があります。


SpringBootSampleApplication.java

Micronaut.run(SpringBootSampleApplication.class, args);



substratevm(AOT)における各設定

ここは・・・どうnative compileするかの定義ですが、細かくみていません。

nettyやlogging関連の設定ですが、とりあえずサンプルからのコピペです。

https://github.com/h-r-k-matsumoto/spring-boot-sample/blob/micronaut-maven/src/main/java/com/example/hrkm/springbootsample/graal/MicronautSubstitutions.java


Build & Run

下記コマンドでdocker imageをビルドします。


build

$ docker build . -t spring-boot-sample:native-maven


実行します。


run

$ docker run -it --rm -p 8080:8080 spring-boot-sample:native-maven

15:28:54.834 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 23ms. Server Running: http://34f44eb544a3:8080

動いているか確認します。

$ curl localhost:8080/sample/hello

hello.% $


結果


得られたもの


  • native-imageによる高速 (~30ms) な起動。


失ったもの



  • actuator が動かない。Micronaut.run に変えて application.yamlから設定を読み込んでくれていない。
    よってhealth checkができずにkubernetesで動かせなかった。いや、path変えればいいんだけども。。。


  • spring.profiles.active など実行時のプロファイル切り替えができない。


補足事項

下記にサポートされるアノテーション、されないアノテーション書いてます。例えば @JsonComponent とかは対応されていないみたいです。

https://micronaut-projects.github.io/micronaut-spring/latest/guide/index.html

今後に期待ですね!

ソースレベルでMicronautにコンバートしてくれた方が嬉しいなぁ。


参考