Lambdaのjava環境をOpenJDKからCorrettoに移行すると利用料金が上がるお話
タイトルは多少誇張したもの。
移行の経緯
AWS Lambdaで利用可能なJavaランタイムをOpenJDKからCorrettoに移行するとの発表があった。
AWS LambdaのJava 8ランタイムがAmazon Correttoへ。OpenJDKから移行するとAWSが発表 - Publickey
これにより、java+Lambdaの利用者は順次ランタイムの移行を行う必要がある。
「CorrettoはAWSが開発してるし、そんな変なことは起きないだろ」と油断してたら刺されるかもしれないという内容。
Correttoにするとメモリが足りない!?
移行検証のために、ランタイムだけ変更して検証を行ったところ、OutOfMemoryErrorが発生してエラーになるという話が出てきた。
確かに利用メモリが最小構成の128MBだったとはいえ、そんなことあるか?ということで、一応検証もしてみることに。
検証の実施
メモリ使用量を出力する処理の実装~jarファイル作成
こちらのページを参考にEclipseでせっせこプロジェクトを作成。
いまからはじめるJavaでAWS Lambda(ラムダ) 前編 - Qiita
InputやOutputは一切不要で、その替わりににメモリの状態を出力するようにハンドラーのコードは下記の通りとした。
package com.sample.lambdatest; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.sample.lambdatest.LambdaTest.Input; import com.sample.lambdatest.LambdaTest.Output; public class LambdaTest implements RequestHandler<Input, Output> { @Override public Output handleRequest(Input in, Context context) { System.out.println("free : " + Runtime.getRuntime().freeMemory()); System.out.println("max : " + Runtime.getRuntime().maxMemory()); System.out.println("total : " + Runtime.getRuntime().totalMemory()); final Output out = new Output(); return out; } public static class Input { } public static class Output { } }
mavenで引き込むaws-lambda-java-core
は1.2.1にバージョンアップした上で、maven packageでFatJarを固める。
AWS上で検証用Lambda関数を作成
マネジメントコンソールからGUIポチポチやって、テスト用の関数を作成。
設定箇所 | 設定値(設定方法) |
---|---|
コード > コードソース | 検証用なので、前手順で作成したjarファイルをローカルからそのままアップロード |
コード > ランタイム設定 > ハンドラ | 実装ソースに合わせてcom.sample.lambdatest.LambdaTest::handleRequest に変更 |
設定 > メモリ (MB) | 128に変更 |
検証してみた結果
CloudWatchLogsの出力は下記の通り。
totalやfreeの値は置いといて、Correttoに移行するとなぜかJava仮想マシンが利用可能と認識するメモリサイズが「約110MB」から「約90MB」程度に低下してしまっている。
検証コードは実処理を行っていないので余裕があるが、FarJarが重量になっているケースや、実業務向けのコードでそれなりにメモリを消費してギリギリを攻めている場合だと、この20MB程度の差で最大ヒープサイズをオーバーする/しないが変化してしまいそうである。
動かなくなった場合に考えられる対応策
- メモリを拡張する(1MB単位で刻めるため、少々気持ち悪いが148などでも設定はできる)
- メモリ使用量を抑えるように処理をチューニングする
- メモリ使用量を抑えるようにFatJarサイズが小さくなるように最適化する
とりあえずメモリ拡張が単純ではあるが、Lambda料金はCPU使用時間 * メモリでかかっていくため、無料枠に収まらないレベルでガンガン実行している関数の場合、AWS利用料金に跳ねてしまう。最小構成128MBで実行できていたものだと、20MB程度の差分を埋めるために148MBにするだけで料金15%アップなので、なかなか憚られる。
対して、元々が無料枠に収まる程度であれば、それほど考えずにメモリ拡張で良いのではないだろうか。
移行すると料金が上がる件まとめ
- OpenJDKからCorrettoに移行すると微妙に利用可能なヒープサイズが減るっぽい。
- メモリ使用量ギリギリのところを攻めていたアプリケーションだと、メモリ拡張やチューニングが必要になりそう。
- 128MBのようなメモリ最小構成から拡張をする場合、10%~20%程度料金アップに跳ねるかも。(キリ良く256MBにすると料金倍…)
- FaaSなのでメモリ最小限で関数を大量に並べるユースケースも結構ありそう。できればAWS側でも改善して欲しい。
- ただ、このケースでのLambda利用時にJavaで実装するか?という疑問は多少ある。
- なぜ利用可能なヒープサイズが減少しているのか見えてない。デフォルトのヒープ割当設定が違うなど?今後余裕があれば調査。