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

[JJUG CCC 2022 fall] Fargate上のJVMからCPUを認識するまで 〜正しく認識されないCPUの謎を追え〜

orekyuu
November 27, 2022

[JJUG CCC 2022 fall] Fargate上のJVMからCPUを認識するまで 〜正しく認識されないCPUの謎を追え〜

orekyuu

November 27, 2022
Tweet

More Decks by orekyuu

Other Decks in Programming

Transcript

  1. Fargate上のJVMからCPUを認識するまで 〜正しく認識されないCPUの謎を追え〜 金川 祐太郎 株式会社ディー・エヌ・エー

  2. 2 自己紹介 金川 祐太郎 • 所属: 株式会社ディー・エヌ・エー • twitter: @orekyuu

    • 最近の悩み: コロナ禍に入ってから太ってしまった 久しぶりに登壇で顔を出したらTwitterで「顔のアス比かわったね」
  3. 3 本日のゴール • 今回の事例を例に、JVMがどのようにCPU数を認識しているかを知る 非ゴール: ECSでJavaアプリケーションを使うためのコツや知見 OpenJDKのコードを読むためのきっかけになれば幸いです

  4. 事例の紹介

  5. 5 環境の紹介 1 • Quarkus: 2.9.2 • JDK: amazon corretto

    17 • quarkus-container-image-jibでビルドしたimageをECS fargateへdeploy
  6. 6 GCのアルゴリズムを指定せず動かすとSerial GCになっている 2 • 負荷試験でJFRの記録をとったところ、 SerialGCが使われていることが分かった • ECS Taskのcpuの指定は2048になっていて、

    G1 GCが使われるはず
  7. 7 目次 OpenJDKのGCに関する登場人物 OpenJDKが使うGC選択の流れ AvailableProcessorsの検出の流れ 1 2 3

  8. 8 OpenJDKのGCに関する登場人物

  9. 9 OpenJDKのディレクトリの構造 • src/hotspot以下にosやcpuアーキテクチャ毎の 実装が書かれており、shareは共通の実装 • share以下は機能ごとにディレクトリが 掘られている 1

  10. 10 登場人物 1 Arguments GCConfig GCArguments SerialArguments SerialArguments initialize GCの決定

    GCアルゴリズムごとの引数 GCアルゴリズムごとにサブクラスを持つ CollectedHeap createHeap
  11. 11 登場人物 1 Arguments GCConfig GCArguments SerialArguments SerialArguments initialize GCの決定

    GCアルゴリズムごとの引数 GCアルゴリズムごとにサブクラスを持つ CollectedHeap createHeap
  12. 12 OpenJDKが使うGC選択の流れ

  13. 13 GCアルゴリズムの決定 1

  14. 14 GCアルゴリズムの決定 1

  15. 15 GCアルゴリズムの決定 1 起動オプションでGCが 明示的に指定されていない

  16. 16 GCアルゴリズムの決定 1 サーバークラスマシンなら G1GC そうでないならSerialGCを選んでいる

  17. 17 GCアルゴリズムの決定 1 active_processor_countが2以上 physical_memoryが約2GB以上 右辺の変数は直前で宣言している

  18. 18 jcmd VM.infoしてみる 2 initial active 1 になっている?

  19. AvailableProcessorsの検出の流れ

  20. 20 active_processor_countの取得 1 os::active_processor_countはosごとに 実装が異なる 今回のイメージでは linuxの実装になる

  21. 21 active_processor_countの取得 1 -XX:ActiveProcessorCountが 指定されている場合

  22. 22 active_processor_countの取得 1 コンテナのときはこちらの処理に入る

  23. ※ここから2022/08頃のコードです OpenJDKのmasterを見ていましたが、変更が入って処理の内容が変わっているためです

  24. 24 active_processor_countの取得 1 CgroupSubsystemとは?

  25. 25 寄り道: cgroups 1 • linuxの機能で、プロセスの利用するリソースに制限をかけるもの • dockerではcgroupsを活用しているらしく、コンテナ対応のコードでcgroups の名前が出てきた

  26. 26 active_processor_countの取得 1 どうやらDockerコンテナのサポート っぽい

  27. 27 active_processor_countの取得 1 share / 1024がshare_countになる

  28. 28 active_processor_countの取得 1 最終的にcpu_countとlimit_countの 小さい値がactive_processor_count

  29. 29 active_processor_countの取得 1 これらのログを確認したい

  30. 30 ログの確認 2 • -Xlogオプションを使う ◦ 今回の場合はjava -Xlog:os+container=trace -versionを ECSのコンテナ内で実行して検証

  31. 31 ログの確認 2 CPU Sharesが2になっている?

  32. 32 active_processor_countの取得 1 share / 1024がshare_countになる

  33. 33 原因を知る 3 • 「詳解: Amazon ECS による CPU とメモリのリソース管理」という記事を読

  34. 34 原因を知る 3 コンテナにCPUユニットを設定しない場合、 2を設定します

  35. 35 原因を知る 3 • ECSにはTask DefinitionとContainer Definitionの両方にCPUの制限をつけられ る • JVMが見ているのはContainer

    DefinitionのCPU制限で、指定をしない場合は2 になる
  36. 36 まとめ 3 • ECSにはTask DefinitionとContainer Definitionの両方にCPU制限があり、JVM が見るのはContainerの方なので必ず宣言しよう • GCは明示的に指定しない場合、意図しないGCになる場合があるので明示的

    に宣言しておくと安心 • -Xlogオプションでログを出力できるので、デバッグする際には活用 してみよう • JDKのコードを読むのは怖くない!みんな読もう!