はじめに
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作れる?と思いましたが、できませんでした。
https://jira.spring.io/browse/SPR-16991
にある通り、GraalVM側での対応も行って上で、さらにSpring Framework側の対応が必要という事なのでしょう。
ただ、下記のようにDIの設定を app.json
のように書き出せば・・・動くのかもしれません。
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アプリケーションを使いました。
変更すること
依存関係の追加。
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に固める際に外しています。
<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を独自に解析する拡張を有効化します。
<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
に変更する必要があります。
Micronaut.run(SpringBootSampleApplication.class, args);
substratevm(AOT)における各設定
ここは・・・どうnative compileするかの定義ですが、細かくみていません。
nettyやlogging関連の設定ですが、とりあえずサンプルからのコピペです。
Build & Run
下記コマンドでdocker imageをビルドします。
$ docker build . -t spring-boot-sample:native-maven
実行します。
$ 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
とかは対応されていないみたいです。
今後に期待ですね!
ソースレベルでMicronautにコンバートしてくれた方が嬉しいなぁ。