JJUG CCC 2020 Fall に参加しました。オンライン開催。簡単に所感をまとめます。
所感
ArchUnit は去年の JJUG でもセッションがあったけど、今回は ArchUnit の柔軟さを生かした応用事例が紹介されていました。いろいろな依存解析が自動化されて可視化されるのはとてもいいけど、あまりやり過ぎるとメンテが大変になりそう。
パフォーマンスチューニングの話はとても参考になりました。「根拠のある改善を行う」というのが刺さる。
Selenide はすごい久しぶりに名前を聞いた気がする。わりと書きやすかった記憶があるので機会があればまた使ってみたいなー。一方で Cucumber はどうなんだろうか。依存するファイルが増えるわりにそれを超えるメリットが今のところ見つけられないんだけど、少し調べてみようかな。
Picocli は去年の JJUG でセッションがあったけど参加できなかったので、今回は話が聴けてよかった。去年くらいに Picocli と Micronaut を試したときのメモ。
Micronaut で CLI アプリケーション + Picocli - kntmr-blog
あと、なんか前も同じことを思った気がするけど、アンカンファレンスが面白そうだったから聴きに行けばよかった...。
現時点では YouTube の動画は非公開になっているようです。アーカイブは公開されるんだろうか。(2020/12/04 追記) セッション動画が公開されました。
以下、メモから抜粋。
痒いところに手を届かせる ArchUnit の利用法 〜アーキテクチャーテストからアプリケーション解析まで〜
- アーキテクチャをユニットテストで実装する
- 依存関係 (パッケージ, クラス, ...)
- 命名規約
- アーキテクチャをテストで明文化 (ドキュメンテーション)
- 部分適用可 (リアーキとか)
- Core API
- クラス, メソッド, フィールドなどの依存関係を取得するためのAPI
- Lang API
- 依存関係の制約を実装するためのAPI
- カスタムルール作成可
- Library API
- レイヤの制約をテストするためのAPI
- BFFはユースケースに合わせたAPI
- バックエンドはリソース指向API
- 別パッケージの類似ドメインクラスを import したり
- 縦方向のレイヤは周知されている
- 水平方向の依存関係をチェックしたい
- 不安定なコードへの依存をテストで制限する
- 変更の影響範囲を機械的に把握したい
- CIで影響範囲を自動でリストアップ☆ > Core API
- リフレクションなどの依存や設定ファイルの変更は検出不可
- サービス間の影響調査
- API/DB間, Android/BFF間 > Android/DB間
- サービス間の依存関係 > 分散トレーシングを使う
- 画面遷移図の自動生成
- バイトコードを解析するので自動生成クラスも解析可
ArchUnit すごい柔軟で便利そうだけど、気が付いたら ArchUnit おじさんが生み出されそう #jjug_ccc #jjug_ccc_a
— kntmr (@knt_mr) 2020年11月7日
パフォーマンスのトラブルシュート入門
- 正しいパフォーマンスチューンングの流れ☆
- アプリの下も把握する必要あり
- フレームワーク, ランタイム, OS, ...
- アプリの事実を計測する > ログ, メトリクス
- 計測する情報
- 各処理 > どこの処理が遅くなっているか
- システム全体 > なぜ遅くなっているか☆
- 遅くなる原因を知るにはシステム全体の視点が必要
- ファイルの読み書きには暗黙的なものもあるので注意
- シェルで記録してバッファ溢れで消えてしまったり
- コンテナを消す前に永続化領域に記録する
- 計測した情報は可視化, 正常期間/異常期間を比較
- 根拠のある改善を行う☆
- 必要な情報を計測する機能を FW が提供しているか
- Java 標準ツール☆
- Unified Logging
- MBean/JMX
- Eclipse MicroProfile Metrics/Health
- JDK Flight Recorder
- 主要なメトリクスを記録
- アプリ独自のメトリクスを作成可
- ログは発生ベースなのでメトリクス収集には向いてない
- 最近の主流は JFR でメトリクス収集
- JDK Mission Control で可視化
- ケーススタディ
- クラウドのサーバーレス環境でJFRは使えるか?
- OpenJDK11以降, ファイルダンプが必要
- デフォルトのプロファイルではCPU1-2%程度のコスト増
Project Reactor でノンブロッキング、非同期処理を実装してみよう!!
- Webフロントエンド, 外部サービス連携, マイクロサービス連携, ...
- 同期, 非同期, ノンブロッキング
- ブロッキング = Worker Thread のスレッドを専有する
- ノンブロッキング = Event Pool
- ノンブロッキングを簡単に実装する > Reactive Streams
- Publisher
- Subscriber
- Subscription (バックプレッシャー)
- Processor (Pub+Sub)
- 非同期, ノンブロッキング
- Pub/Subモデル
- バックプレッシャー
- Project Reactor
- Mono, Flux
- subscribe, doOnNext, doOnError, doOnComplete, ...
- Subscriber 側が subscribe するまで何も起きない
Subscription#request
(バックプレッシャー)- Subscriber 側でリクエスト量を制限する
- map, flatMap
- map はシーケンシャルに処理する
- flatMap は新しい publisher (mono) を返す
- Cold Publisher > リクエスト時点で処理開始
- Hot Publisher > Subscribe 時点で処理開始
- Azure SDK で非同期/ノンブロッキングを実装
- Project Reactor を使う
- Reactive Route (Quarkus)
- ChangeFeedProcessor (Cosmon DB)
- CQRS の実装で使うと便利?
Javaコードが速く実行される秘密 - JITコンパイラ入門
- cafe babe
- javac, javap
- JVM は処理をインタプリタ実行する
- JIT コンパイル
- プロファイル情報
- コードがどのように実行されているか
- よく実行される処理が JIT コンパイル対象になる
- HotSpot
- C1, C2
- C1 コンパイラ (client コンパイラ)
- C2 コンパイラ (server コンパイラ)
- 階層型コンパイル
- C1 と C2 の両方/段階的に使う
-Xint
インタプリタモード (JIT コンパイルなし)- 最適化レベル (0-4)
- 1-3 は C1 コンパイラ
- C2 コンパイルした機械語があまり使われないとき
- キャッシュから削除される (最適化レベル 4 → 3)
- HSDIS (HotSpot Disassembler)
- JITWatch
- Java バイトコード > IR (中間表現) > 機械語
- JVM ではプログラムの依存をグラフで表現している
- IR グラフ
- GraalVM JIT コンパイラ
- JIT コンパイル
- フロントエンド > 高レベルなIR
- バックエンド > 低レベルなIR (ハードウェア寄り)
- ホットパスでのコンパイル
- GraalVM は Java ベース
- C++ より敷居が下がる
- ゼロベースで作り直されてるのできれいになっている
LINE ShopチームでのSREの取り組み
- Prometheus + Grafana
- Armeria
- マイクロサービス
- 分散トレーシング > Zipkin
- Redisクライアント側で取る?
- Circuit Braker (Cascading Failure)
- FailFastException を catch して fallback する
- Graceful Degradation
- 障害発生時、継続させたい機能は何か
- 一部機能はレスポンスの質を低下させても継続可能か (キャッシュの古いデータを返したり)
- Service Discovery
- Central Dogma
- Prometheus
- Central Dogma
- https://line.github.io/centraldogma/
- 設定リポジトリサービス
- 各サービスが watch して変更通知を受ける
- Rate Limit 設定, A/B テスト, ...
- SLI, SLO
- モニタリング
- アラートレベルで通知する Channel を分ける
- ユーザーに直接影響がある > Error
- サービス影響が少ない, 問題の原因になり得る > Warn
- アプリケーション固有のメトリクス
- バージョン (アプリ, FW, ...)
- バッチのモニタリング
- Prometheus は Pushgateway からメトリクスを pull する
- インシデント対応
- アラート対応ガイド
- 必要に応じてレポート作成 > SRE ポストモーテム
- ポストモーテム
- キャパシティプランニング
- イベントに備えてスケールアウト/スケールアップ
- スパイクへの対処
- Rate Limit でリクエスト量を制限する > Central Dogma の管理画面から設定
- スケールアウト
- k8s
- Verda (Private Cloud) の VM/物理サーバー
- Ansible でプロビジョニング
- スケールアウトに時間がかかる
- モニタリング
- サービス全体で収集しているメトリクスは600万+
- Pod のメトリクスはリバースプロキシアプリ経由
- メトリクス
Head toward Java 15 and Java 16
- Incubator, Preview, Standard
- Pattern Matching for instanceof
- Text Block
- Records
- equals フィールドが同値の場合は常に true を返す
- リフレクション不可
- Local records
- Sealed Classes
permits
- パターンマッチ
- Hidden Classes
- 基本的にはフレームワーク/ライブラリで使われる
- Foreign-Memory Access API
- UDP Socket API
- Vector API
- Elastic Metaspace
- Shenandoah GC, ZGC
- JS エンジンは GraalJS への移行を推奨
Sealed Classは今までpackage-privateとかprotectedとかのアクセス制御で継承先を制限したりしていたのが明確にこのクラスだけと指定できるようになったので誰が責務を持つのかを明確に「コード」で表現できるようになったのがメリットです #jjug_ccc #jjug_ccc_a
— KUBOTA Yuji (@sugarlife) 2020年11月7日
OAuth 2.0 with Spring Security
- OAuth 2.1
- spring-boot-starter-oauth2-client
- RestTemplate を使うところではタイムアウトを設定すること☆
client#setRestOperations(restTemplate)
- WebClient も同様
- connection/read/write
- 5.0 以降では WebClient への移行を推奨
- おそらく RestTemplate がすぐに削除されることはないはず
- spring-boot-starter-oauth2-resource-server
- Token Introspection
- 認証方法のカスタマイズ
- OpaqueTokenIntrospector を実装する
- Token Propagation
- 認可サーバー
- Spring Authorization Server (開発中)
Selenide Cucumber で実現する UI テスト自動化 BDD
- Selenide
- Cucumber
- Selenide + Cucumber
- steps ファイルに Selenide のテストを実装
- アンチパターン☆
- ドメインごとに steps ファイルを作成する
- BDD
- 画面ありのアプリで TDD が実現できる
- feature ファイル変更
- 対応する steps ファイル変更
- Page Object 変更
- テスト失敗
- プロダクションコード変更
- 創発的設計
- スクリーンショット可
- テスト失敗のみとかも可
JavaとpicocliとGraalVMでときめくCLIアプリを作ろう
- Java で単一コマンドアプリケーションが作れる
- JRE だけで 200 MB (重い)
- JLink, JPackege
- GraalVM
- ネイティブイメージの弱点☆
- AOT はコマンドラインアプリにピッタリ?
- System.out, System.err, 終了コード
- サブコマンド
- refrect-config.json 自動生成
- picocli-codegen
- Micronaut と Quarkus には picocli が組み込まれてる