2020-06-16 JSUG勉強会 2020年その5 Spring Boot 2.3 徹底解説 #jsug
2020/06/16 に開催された JSUG勉強会 2020年その5 Spring Boot 2.3 徹底解説 のイベントレポートです。
●イベント概要
2020年5月にSpring Boot 2.3がリリースされました!
これを記念してBoot 2.3の新機能+αをご紹介します。
セッション概要
Deep dive into Spring Boot 2.3
先月リリースされたSpring Boot 2.3の新機能の詳細を解説します。
・Kubernetes Support (Liveness/Readiness Probe, Graceful shutdown)
・Docker Image Support (Cloud Native Buildpack, Layered Jar Format)
・その他の細かい変更
・2.3へのアップデートの注意点
Spring Boot 2.2までを使っている方を想定して話します。
■Deep dive into Spring Boot 2.3
Toshiaki Maki さん [VMware]
※スライドはURLが変更になることがあので、ブログのリンクから参照してくださいとのことでした。
●Release Cadence Change
・もともと
一年に1回
Spring Frameworkに合わせてマイナーバージョンがあがる
→ 半年に一回に変更
●主な変更内容
・k8s support
・Livenes / Readiness Probe のサポート
・Graceful Shutdown のサポート
・k8sではなくても使える
●Livenes / Readiness Probe のサポート
・Actuator Healthcheck
/actuator/health でアクセス
アプリが利用する外部サービスの状態をチェックするもの
複数のHealthIndicatorの集約結果
・k8sでこの結果を利用すると
外部のサービスのチェックで、自身のコンテナを再起動
これでは回復しない
・Liveness State
内部の状態を返す
NGの場合、再起動されるべき
・Readines State
Trafficを受けられう状態かを返す
NGの場合、Trafficは遮断されるべき
・Application Startのフェーズ
Starting
Liveness: BROKEN
Readiness: REFUSING_TRAFFIC
Started
Liveness: CORRECT
Readiness: REFUSING_TRAFFIC
Ready
Liveness: CORRECT
Readiness: ACCEPTING_TRAFFIC
・Application EventFlow
Application Starting Event
Environmentが利用可能になった
Context作成後
Bean定義のload後
Application, Command Runner実行前
LivenesState.CORRECT
Application, Command Runner実行後
ウォームアップなど
Trraficを受け付ける前に実行したい処理を定義できる
ReadinesState.ACCEPTING_TRAFFIC
・エンドポイント
/actuator/health/Liveness
/actuator/health/readiness
・デフォルトはOFFになっている
k8s環境にデプロイするとON
・設定
management.health.probes.enabled=true
spring.main.cloud-platform=kubernetes
・/actuator/health
これらの結果も集約
・プログラムからコンテナを再作成させる
AcailabilityChangeEvent.publishで
LivenessState.BROKEN
・k8sで任意のコマンドをprobeに指定する場合
cat /tmp/ready を指定する例
@EventListenerメソッドで
ACCPTING_TRAFFICだったらファイル作成
REFUSING_TRAFFICだったらファイル削除
のような使い方もできる
・どうしても外部のサービスのチェックを含めたい場合
できるだけ外部は見ない
前提となるサービスが起動していないといけないなど
management.endpoint.health.group.readiness.include
=readinessState,db,redis
●GracefullShutdown
・shutdownが動き始めてから
新しいリクエストが来たり
処理中のリクエストが残っていたり
・SpringBoot2.2 まで
ServletContainerごとにハックしていた
・Shutdownの前にGraceful Shutdown処理ができた
application.properties
server.shutdown=graceful
spring.lifecycle.timeout-per-shutdown-phase=10s
デフォルトは30s
k8sは30s、CloudFoundryは10s
プラットフォームに合わせて設定
●configuration fileのワイルドカード読み込みをサポート
・ConfigMapで用途別のpropsを用意したい場合に便利
・デフォルトで /config/*/application.properties をロード
/config/redis/application.properties
/config/mysql/application.properties
など
●Docker Image Support
・CloudNative Buildpacks
・Layered Jar Format
●CloudNative Buildpacks
・よくあるだめなDockerfile
FROM openjdk:8-jdk-alpine
COPY target/*.jar app.jar
ENTRYPOINT ["java", "-Xmx2g", "-jar", "app.jar"]
・本格的には100行+必要
Dockerfile Best Practices でも足りない
これをコピペして管理、、、
・CloudFoundry、Herokuではソースからcontainer imageをつくっている
Here is my source code
Run it on the cloud for me
I do not care how
→ Buildpack
・Cloud Native Buildpacks
OCI標準のコンテナイメージに変換
ポータビリティ、ビルド高速化、ローカル環境でh実行可能
ベストプラクティスで書いたものと同等
・maven/gradle pluginを追加
paketoを利用
mvn package の代わりに
mvn spring-boot:build-image
で jar + OCI image
・pomに合わせてJREダウンロード
BellSoft Liberica
IntelliJ ideaと同じもの
・ヒープサイズとノンヒープサイズを算出
コンテナのメモリサイズ、jarのクラスファイル数から
・Dockerfileでつくったimageとの違い
docker push, pull が早い!
dockerfile
base image
+ 再利用されない中間layer
+ app
CloudNative Buildpacks
base image
+ 再利用される中間Layer
JRE, Memory Calculator, JVMKill ...
+ app
・コンテナでJavaアプリに必要なメモリの考え方
コンテナのメモリ 1024MB
Javaアプリのメモリ
Heapは少ない
Non Heapが複数
Java以外(Head Room)
-Xmx, -XX:MaxMetaSpaceSize, ReservedCodeCacheSize...
設定しきれない、、、
・Memory Calculatorが自動設定
MetaSpace
class数から計算
ThreadStack
スレッド数の掛け算で計算が必要
デフォルトは 250 thread
= tomcatのmax200 + 周辺
コンテナのメモリサイズが不足すればエラーになる
デフォルトだと 700m程度のメモリサイズが必要
docker run -m 512m -e BPL_JVM_THREAD_COUNT=30
docker run -m 256m -e JAVAOPS="-XX:ReservedCodeCacheSize=32M -Xss512k"
指定できる環境変数はbuild時のログに出ている
・JVMKill Agent
OutOfMemoryError
動けないのにプロセスが残って、ずっとタイムアウト
プロセスをkillするべき
設定
-XX:+ExitOnOutOfMemoryError
-XX:OnOutOfMemoryError='kill -9 %p'
この代わりにkillするJVMTI Agent
●Layered Jar Format
・CloudNativeBuildpacksで
アプリケーション以外のlayerが再利用されるようになった
・アプリケーションのlayer
dependencies
spring-boot-loader
snapshot-dependencies
application
・これらを分ければ更に効率が良い
サンプルでpushするレイヤーサイズは KB単位に
・利用方法
pom.xml
spring-boot-maven-plugin/
configration/layered = true
・それでもDockerfileを書きたい
jar -Djarmode=layertools で、レイヤーを分けて展開できる
dockerfileでmultistage buildすれば、手書きにも利用できる
●その他の変更点
・Java 14 support
・Spring Dataの各実装がアップグレード
R2DBC, Couchbase v3, Cassandra v4,
MongoDB 4, Elasticsearch 7.5+
このサイクルに追いつくのがケーデンス変更の目的の一つ
・Spring Security 5.3
・RSocket 1.0
・Micometer 1.5
●2.3に上げるときの注意点
・デフォルトのエラーメッセージが空になった
誤って重要な内容をメッセージで表示してしまったりを防ぐ
server.error.include-message
server.error.include-binding-errors
always, never, on_param
・spring-boot-starter-validationが含まれなくなった
あまり使われていない、起動に時間がかかる
bean validationが必要な場合は、dependency追加
Hibernete Validation 6.1から日本語メッセージ対応
-Duser.language=en でもとに戻る
・BootstrapMode for JPA repositories
spring.data.jpa.repositories.bootstrap-mode=deffered になった
・spring-boot-properties-migrator
非推奨になった設定項目をログに出してくれる
●Wavefront Spring Boot Starter
・SaaSのモニタリングサービス
フリーミアムアカウントをSpring Boot経由で作成できる
すぐにRED method
すぐに分散トレーシング
フリーアカウントは容量制限あり
・接続情報はログに出る
application.properties に貼って
同じWavefrontプロジェクトにデータを送る
invite userで自分を招待しておくと便利
●Spring GraalVM Native 0.7
・Springのwebアプリケーションを高速に起動
・これまでは、色々変更してnative imageをつくっていた
JVM切り替え、設定変更など
・多くのアプリが、変更なしでビルドできるように
サンプルのpetclinicも変更なしでOK
・消費メモリが小さくなった
・ビルド用コンテナ
localを汚さないで済む
・SpringCloud Functionもサポート
AWS lambdaでも動かせるっぽい
・jafu
DSLで記述
最速のwebapp 0.02sec
他のサンプルで0.4sec程度
コミュニティで上がった声がどんどん実装されていく
spring bootをアップデートするだけで利用できるのはありがたい
■感想
久しぶりにSpring Bootの状況を知りましたが、めちゃくちゃ便利になってますね!k8s、OCIサポートも手厚い!
wavefrontは知りませんでしたが、フリーで、サクッとRED methodに沿って始められて、分散トレーシングもできるならかなり便利そうですね。
支援先の調査で TKG / TAS → PKS / PAS → CFCR / CFAR / BOSH と遡って、先週から情報を追いはじめました。cfdevでサンプルのjavaアプリをデプロイした時に、かなりメモリを割り当てないとデプロイできなかったのですが、今回の説明で Memory Calculator の設定をしてなかったからだと理解できました。設定方法もさっと教えていただけてとても助かりました!
サンプル
Makiさん、運営の皆さん、ありがとうございました!
この記事が参加している募集
いつも応援していただいている皆さん支えられています。