Spring FuをGraalVMで動かす。起動速度に驚いた。

Serverlessプラットフォームが注目される中、その潮流にJava勢も乗っかりたいので起動速度が速いと注目のGraalVMを試してみた。

モチベーション

  • GraalVMのアプリケーション起動までを理解したい。
  • GraalVMでSpring Fuを動したい。
  • GraalVMでHTTP/1.1とgRPCのエンドポイントが開いたサーバを動かしたい。

GraalVMコトハジメ

GraalVM周辺を理解する。

https://www.graalvm.org/

GraalVMとは

  • Polyglot VM。多言語用の仮想マシンである。
  • JavaのJVMもScala/Java/Kotlinの複数言語を実行できたがGraalVMはJavaScript、Python、Rubyなどの言語も実行できる。
  • KotlinでRubyの関数を呼び出すことが可能。
  • Twitterは本番環境に導入しているらしい。

GraalVMとGraal

  • GraalとGraalVMを混同してしまうが別物である。
  • GraalはJavaのJITエンジンの1つでGraalVMはJITコンパイラにGraalを使っている。
  • Java9のAOTコンパイラはGraalをつかっている。

AOTコンパイラ

  • GraalVMではAOTコンパイラをつかってnative imageを作れる。
  • これにより起動が爆速になる。
    • JVMのJITコンパイラ(Just-in-time:実行時コンパイル)は実行時にコンパイルされるがAOTコンパイラ(Ahead-of-time:事前コンパイル)は事前コンパイルのため予めVM上で動く機械語にコンパイルされるため起動が速い。

GraalVMのメリット

  • 多言語を1つのランタイムで動かせること。
  • デプロイ構成や監視体制など言語ごとに整える必要がなくなる。
  • 起動が爆速。KnativeなどのServerlessプラットフォームと相性が良い。

GraalVMのデメリット

  • 動的なクラスなクラスロードができない。

GraalVMでSpring Fuを動かす

  • Spring Fuで実装したアプリケーションをGraalVMで動かす
  • サンプルで試したアプリケーションではHandlerをbean化しているがnativeイメージ化するためには一工夫必要である
native-imageのコマンド
 native-image -H:Name=app \
  --delay-class-initialization-to-runtime=io.netty.handler.codec.http.HttpObjectEncoder,org.springframework.core.io.VfsUtils \
  -H:ReflectionConfigurationFiles=graal-app.json \
  -Dio.netty.noUnsafe=true \
  -H:+ReportUnsupportedElementsAtRuntime \
  -Dfile.encoding=UTF-8 -cp ".:$(echo spring-fu-on-graalvm/BOOT-INF/lib/*.jar | tr ' ' ':')":spring-fu-on-graalvm/BOOT-INF/classes me.soushin.app.ApplicationKt

-H:ReflectionConfigurationFiles=graal-app.jsonがポイントである。 このjsonに次のようにbean化するクラスを定義する。

  {
    "name": "me.soushin.app.EchoHandler",
    "allDeclaredConstructors": true
  }

こうすることでSpringの世界で bean<EchoHandler>()を読んでも動的クラス読み込みが成功する。

起動にかかった時間を確認する

04:15:42.131 [main] INFO org.springframework.boot.SpringApplication 
  - Started application in 0.012 seconds (JVM running for 0.012)

0.012!! 爆速。

Spring Fuを動かしているレポジトリを公開しているのでソースとともに確認してほしい。

github.com

gRPCサーバは動くのか

こちらのレポジトリで試したがnative imageの生成時にエラーを確認した。

github.com

oracle/graalにissueを送ったので継続してgRPCサーバを動かすことにチャレンジしていきたい。

github.com

まとめ

  • GraalVMのコトハジメをまとめた。
  • JVMは起動速度がネックであったがServerlessプラットフォームに相性が良いGraalVMは利用が広がっていくのではないだろうか。
  • ビルドの工程にnativeイメージを固めることが加えられるので時間は増すが起動時間短縮のメリットがある。
  • 実践導入に向けた試験など課題はあるがスモールなサービスから投入して慣らしていきたい。