Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Server-Side Kotlin アプリのCloud Run コールドスタート レイテンシ...

Server-Side Kotlin アプリのCloud Run コールドスタート レイテンシを改善した話

■イベント
サーバーサイドKotlin LT大会 vol.11
https://server-side-kotlin-meetup.connpass.com/event/309183/

■発表者
技術本部 Bill One Engineering Unit
柳浦 豊

■Bill One 開発エンジニア 採用情報
https://media.sansan-engineering.com/billone-engineer

SansanTech

March 08, 2024
Tweet

More Decks by SansanTech

Other Decks in Technology

Transcript

  1. Sansan株式会社 部署 名前 Server-Side Kotlin アプリの Cloud Run コールドスタート レイテンシを改善した話

    Sansan技術本部 Sansan株式会社 技術本部 Bill One Engineering Unit 柳浦 豊
  2. 柳浦 豊 Sansan株式会社 技術本部 Bill One Engineering Unit 2022年に Sansanに中途⼊社し、⼊社以来

    Webアプリケーショ ン開発エンジニアとしてBill Oneの開発に従事しています。 マイクロサービスや CI/CDに興味・関⼼があります。 やぎうら
  3. Sansan株式会社の働き⽅を変えるDXサービス 個⼈向けサービス 請求書受領から、 ⽉次決算を加速する インボイス管理サービス 契約データベースから、 収益を最⼤化する 契約データベース 営業DXサービス 名刺管理から、収益を最⼤化する

    あらゆる顧客接点で 営業機会を逃さない マルチチャネルフォーム 法⼈向けサービス 名刺アプリ タッチで交換。スマートに管理。 受注業務のDXから、 事業を加速する 受注管理サービス 1 設⽴ 2007年6月 資本⾦ 事業 働き⽅を変えるDXサービスの 企画・開発・販売 東京証券取引所 プライム市場 上場証券取引所 表参道本社 Sansan パラシオ 関⻄⽀店 福岡⽀店 中部⽀店 拠点 第三者機関認証の 取得状況 ISO/IEC 27001(ISMS) ISO/IEC 27017 JIS Q 15001(Pマー ク) 66億88百万円 (2023年11月30日時点)
  4. Google Cloud のコンピューティングプラットフォームの⼀つ • フルマネージド • コンテナを直接実⾏可能 • サービス型とジョブ型の⼆種類:今回はサービス型のお話 •

    サービス型はリクエストベースで⾃動スケーリング ◦ ⼀定時間リクエストがなければゼロインスタンス(無課⾦) ◦ ⼀つのインスタンスで複数リクエストを並列処理可能(最⼤同時実⾏数の設定) Cloud Run 7 出典: https://cloud.google.com/run/docs/overview/what-is-cloud-run
  5. • コールドスタート ◦ スケールアウト時に⾏うコンテナ初期化処理 • コールドスタートレイテンシ ◦ 新規コンテナが応答できるようになるまでの 時間 ◦

    その間、リクエストは待たされる • いつスケールアウトするか? ◦ ゼロインスタンスからのリクエスト発⽣時 ◦ リクエストが急増し、起動済みインスタンス で処理しきれないとき ◦ CPU 使⽤率がしきい値を超えたとき Cloud Run コールドスタート 出典: https://cloud.google.com/blog/ja/products/serverless/lifecycle- container-cloud-run
  6. • 当初の Bill One の Kotlin アプリ: 約5.0sec ◦ 軽量フレームワークの

    Ktor を利⽤ (JVM アプリにしては起動が早い) • あるタイミングからレイテンシが悪化: 約11.5sec ◦ オブザーバビリティ向上のために導⼊した⾃動計装が影響 ◦ OpenTelemetry Java Agent ▪ Java 標準ライブラリに⾃動計装のためのバイトコードを動的に注⼊ ▪ Bill One では OpenTelemetry のディストリビューションの1つである Splunk製 Java Agent を使⽤ Java Agent: クラスローディングをフックし、前処理追加やクラスの書き換えを⾏う Java の仕組み Bill One Kotlin アプリのコールドスタートレイテンシ
  7. • アプローチ1: 起動時間短縮 ◦ CPU スケールアップ ▪ vCPU 追加 ▪

    Startup CPU Boost オプション ◦ Cloud Run 第⼀世代を使う (Bill One はもともとこちら) ◦ JVM アプリの起動処理をチューニング • アプローチ2: スケールアウトを最⼩限にする ◦ Cloud Run Min Instance オプション ▪ 指定した数のコンテナを停⽌させずアイドル状態で維持し続ける ▪ アイドル状態時は通常時の1/10の料⾦が課⾦ ▪ Min 数でトラフィックをさばけない場合は、スケールアウトが発⽣するため、 ⼗分な Min を確保する必要がある コールドスタートレイテンシの改善⽅法
  8. • アプローチ1: 起動時間短縮 ◦ CPU スケールアップ ▪ vCPU 追加 ▪

    Startup CPU Boost オプション ◦ Cloud Run 第⼀世代を使う (Bill One はもともとこちら) ◦ JVM アプリの起動処理をチューニング • アプローチ2: スケールアウトを最⼩限にする ◦ Cloud Run Min Instance オプション ▪ 指定した数のコンテナを停⽌させずアイドル状態で維持し続ける ▪ アイドル状態時は通常時の1/10の料⾦が課⾦ ▪ Min 数でトラフィックをさばけない場合は、スケールアウトが発⽣するため、 ⼗分な Min を確保する必要がある コールドスタートレイテンシの改善⽅法
  9. • 計測指標 ◦ Cloud Run ⾃動 Monitoring 指標: “cloud_run_revision -

    run/container/startup_latencies” • 課題 ◦ 評価データを収集するため、意図的にコールドスタートを繰り返したい • ⼯夫 ◦ 30分間隔のリクエスト送信により、確実にコールドスタートさせられる ▪ 参考記事:https://zenn.dev/cloud_ace/articles/bd95501cb0cd3f ▪ Cloud Run は最⼤で15分間のアイドル状態を経て、シャットダウンする仕様 コールドスタートレイテンシの計測指標と⼯夫 出典: https://cloud.google.com/blog/ja/products/serverless/lifecycle-container-cloud-run
  10. • コールドスタート中とその後の10秒間のみ、一時的に vCPU 上限を引上 げるオプション ◦ 追加 vCPU 数は Cloud

    Run サービスの vCPU 上限設定により異なる(1〜4 vCPU を追加) ◦ Boost 後は通常の vCPU 上限設定が適用されるため、コストを抑えつつコー ルドスタートレイテンシを短縮できる ◦ 今回のケース ▪ Boost により vCPU 上限 2 をコールドスタート時に 4 に引き上げ 改善1: Startup CPU Boost オプション 参考: https://cloud.google.com/run/docs/configuring/cpu?hl=ja#startup-boost
  11. • デフォルトではすべての⾃動計装が有効 • 環境変数などで不要な⾃動計装を無効にして起動時間を短縮できる • 例:AWS SDK, Akka HTTP 向けの⾃動計装を無効化

    改善2: Splunk Otel Java agent オプション 参考: https://opentelemetry.io/docs/languages/java/automatic/configuration/#suppressing-specific-agent-instrumentation OTEL_INSTRUMENTATION_AWS_SDK_ENABLED=false OTEL_INSTRUMENTATION_AKKA_HTTP_ENABLED=false …
  12. • JIT コンパイラとプロファイリング最適化 ◦ 最適化レベルを落とすことで起動時間を短縮できる ▪ C1: クライアントアプリ向けコンパイラ ▪ C2:

    サーバーアプリ向けコンパイラ:⻑時間稼働するサーバー向 けにより⾼度に最適化 ◦ 実⾏時間の短いアプリでは⻑期的な効率性よりも起 動時間短縮を優先させるメリットが⼤きい • JVM オプションに以下を追加 ◦ -XX:+TieredCompilation : 階層型コンパイルを有効化 (JDK 8 以降はデフォルト有効) ◦ -XX:TieredStopAtLevel=1 : 階層型コンパイルレベルの上限 改善3: JIT 階層型コンパイルレベルを抑制 レベル コンパイラ プロファ イリング 4 C2 - 3 C1 完全プロ ファイリ ング 2 C1 基本プロ ファイリ ング 1 C1 なし 0 インター プリタ -
  13. 改善1〜3によるレイテンシの短縮効果 改善方法 改善時間 startup CPU Boost 1秒 Otel Options 1秒

    Compile Level 抑制 1.5秒 合計 3.5秒 約11.5sec 約8.0sec 改善前 改善後 30%短縮
  14. • AppCDS (Application Class Data Sharing) ◦ アプリ起動時に必要なクラスロード処理結果を保存することで、次回の 起動処理を短縮する ◦

    Open JDK の AppCDS は Java agent との組み合わせは不可 ▪ テスト⽤途向けで本番環境向けは⾮推奨 (https://bugs.openjdk.org/browse/JDK-8213813) ◦ ⾃動計装を外すなら有効にできるが⾃前計装とのトレードオフ • 検討中 ◦ CRaC (Coordinated Restore at Checkpoint) ▪ 起動中の JVM プロセスの状態を保存し復元する ◦ GraalVM の Native Image ▪ 起動前にすべて Native コードに変換しておく 他の改善案
  15. • Cloud Run の⾃動スケールアウトを活⽤するにはコールドスタ ートレイテンシをできる限り短くしたい • ⾃動計装による JVM アプリへの影響は思いの外、⼤きかった ◦

    今回のケースでは 5.5sec 増加 • 3種類の改善を組み合わせて、コールドスタートレイテンシを 約 30% 短縮できた ◦ 11.5sec → 8sec まとめ