Fly.ioの無料枠へSpring Bootアプリケーションをデプロイする
概要
Fly.ioの無料枠で使えるVM(CPU 1 shared、RAM 256MB)へSpring Bootアプリケーションをデプロイしたのでポイントをメモしておきます。
Cloud Native Buildpacksでビルドしたコンテナイメージをデプロイする
コンテナイメージのビルドにはCloud Native Buildpacksを使えます。
fly.toml
へ次のように記述します。
[build]
builder = "paketobuildpacks/builder:base"
[build.args]
BP_JVM_VERSION = "17"
BPE_BPL_JVM_THREAD_COUNT = "30"
BPE_DELIM_JAVA_TOOL_OPTIONS = " "
BPE_APPEND_JAVA_TOOL_OPTIONS = "-XX:ReservedCodeCacheSize=30M -Xss256k"
BPE_SERVER_TOMCAT_THREADS_MAX = "10"
BP_JVM_VERSION
でJavaバージョンを設定しています。
詳細はbellsoft-liberica
のGitHubリポジトリを参照してください。
BPE_
から始まる変数でコンテナイメージへ埋め込む環境変数を設定しています。
詳細はenvironment-variables
のGitHubリポジトリを参照してください。
設定している環境変数の内容については後述します。
設定している環境変数の内容について(メモリー計算)
VMのメモリーが小さいため何も設定しないでいるとSpring Bootアプリケーションは動いてくれません。
Javaのメモリー計算はJavaビルドパックのリファレンスが参考になります。
コードキャッシュ、スレッドスタックのサイズだけで合計490MBが必要になるため、これらを削って非ヒープを100MB台まで絞ります。
コードキャッシュを削る
コードキャッシュはデフォルト240MBです。
まずはNative Memory Trackingでどれぐらいコードキャッシュを使っているか確認します。
ローカルで-XX:NativeMemoryTracking=summary
を付けてアプリケーションを起動し、jcmd
のVM.native_memory
を見てみます。
- Code (reserved=249004KB, committed=21576KB)
(malloc=1320KB #7501)
(mmap: reserved=247684KB, committed=20256KB)
コードキャッシュで約21MB使用していました。
余裕を持たせて30MB確保しておきます(-XX:ReservedCodeCacheSize=30M
)。
スレッドスタックを削る
次にスレッドスタックを削ります。
1スレッドあたりのスレッドスタックがデフォルトで1MB、それからコンテナイメージに設定されたメモリー計算用のスレッド数が250なので、1MB * 250 = 250MBとなります。
250という数はSpring Bootの組み込みTomcatの最大スレッド数(200)と、それ以外のスレッド数(50)を合わせたものです。
今回のアプリケーションは主に私しか使わないのでTomcatのスレッドは10もあれば十分です(BPE_SERVER_TOMCAT_THREADS_MAX = "10"
)。
またVMのメモリーが256MBと小さいためG1GCは使われずシリアルGCになり、GCに使用されるスレッドがかなり少なくなることも考慮し、全体で30スレッドを見込んでおくことにしました(BPE_BPL_JVM_THREAD_COUNT = "30"
)。
さらに1スレッドあたりのスレッドスタックも1MBから256KBへ減らしています(-Xss256k
)。
少しずつ値を変更しつつ計測したところ最低限170KBでも一通り動作したので、余裕を持って256KBとしました。
これでスレッドスタックに割くメモリーは256KB * 30 = 7680KB = 7.68MBとなります。
ダイレクトメモリーとメタスペースを含めても非ヒープを130MB程度に抑えられました。
おわりに
以上のようにメモリーのチューニングをする必要はありましたが、無事にFly.ioの無料枠でSpring Bootアプリケーションを動かせられました。
Discussion