[Java] 2017/03/21 JJUG ナイト・セミナー 参加メモ #jjug

2017/03/21に開催されたJJUG ナイト・セミナー 「Enterprise Java最新動向〜Java EE 8とMicroprofile〜」に参加した際のメモ書きです。
気が向いたら内容を整理するかも。

Java EE 8の最新状況について

Java EE 8は仕様はFIXしていないので注意

GlassFish5

  • Promoted Buildがリリースされた3/13
    • Java EE 8 CTS実施済み
    • Nightlyは限定したテストケースのみ

Schedule

  • Final: 2017/07

Spec Status

  • 大体は、Public Draftが出ている
  • MVC 1.0はdropされているのは周知の通り(コミュニティに移管)

各Specについて

JAX-RS 2.1

  • Reactive Client API
  • Server-Sent Events
  • Non-blocking I/O

歴史

  • 1.1: クライアントAPIが未定義のため、各JAX-RS実装の独自API、Apache HttpClient等が使われた
  • 2.0
    • クライアントAPI追加
    • RESTリソース(WebTarget)の生成が可能に
    • 非同期呼び出し(.async()をコールするだけ、コールバックオブジェクト(InvocationCallback)の登録も可能)
    • リアクティブプログラミング的な実装をする場合、InvocationCallbackがネストしてかなり気持ち悪い(callback hell)

2.1

  • SyncInvoker, AsyncInvoker(.async())に加えて、RxInvoker(.rx())が追加された。戻り値はCompletionStage
CompletionStage<Number> price = client.target(...);
CompletionStage<String> wheather = client.target(...);

price.thenCombine(wheather, (price, wheather) -> reserveIfAffordable(price, wheather));
// ^ priceの結果とwheatherの結果を受けて次の処理を行う。chain
// ^ TODO 後で調べる: CompletableFuture
  • Reactive API Pluggability
    • 3rd party Reactiv Frameworkを利用できる
    • RxJavaの場合、RxFlowable<Response> flowable = client.target(...).request().rx(RxFlowableInvoker.class).get();
      • .rx()の引数に、RxInvoker継承クラスを指定する

Server-Sent Events(SSE)

  • Jersey 2.8では先行して実装
  • サーバーからクライアントへの一方向通信のチャンネル確率
  • event, data, id, retry, comment
  • モダンブラウザサポート
  • WebSocketは専用のプロトコル(ws://)だが、Server-Sent EventsはHTTPベース
  • SseEvent, OutboundSseEvent(サーバサイド), InboundSseEvent(クライアントサイド)
    • SseEventSync(サーバサイド), SseEventSource(クライアントサイド)
    • 2017/02 SSE周りの仕様は変更されているので、最新の情報に注意(Jersey独自実装部分が変わっている

JSON-P 1.1

  • RFC 7159に対応(1.0はRFC 4627)
    • トップレベルにおける要素がObject,Arrayしか無かったが、RFC 7159では全部置ける
  • JSON Pointer
    • JSON中の特定の値を参照するための文字列の構文
    • /0/user/address
    • JsonPointer, JsonPointer#getValue
  • JSON Patch
    • JSONを部分的に変更するような演算
    • add/remove/replace/move/copy/test
    • パッチ自体もJSONで記述される
    • op(操作)とpathと(必要なら)値を指定するJSONで記述されたパッチを、別のJSONドキュメントに適用する
  • JSON Merge Patch
    • RFC 7386
    • Key-Value形式のパッチを渡すと、ReplaceなりAddなりをしてくれる(同一のキーがあればreplace, 無ければadd, Valueがnullならremove)
  • Patch Diff
    • JsonPatch#diff, JsonMergePatch#diff`
  • Stream API対応: JsonCollectors

JSON-B 1.0

  • XMLに対するJAX-Bに似たAPI
  • ClassとJSONのマッピング、マッピングのカスタマイズ
  • デフォルトであればAnnotation/Configは不要
  • @JsonbFooBarアノテーションで、カスタマイズ可能
    • Keyを変える
    • Nullを出す/出さない
    • 日付/数値のフォーマット
    • etc…
  • JAX-Bと同様に、Adaptersも使える
    • アノテーション使いたくなければこっち

Servlet 4.0

  • HTTP/2 サポート
    • Request/Response Multiplexing(ストリーム多重化)
    • Server Push
    • Upgrade From HTTP 1.1 (HTTP Upgrade)
      • ALPNはJava 9で対応予定
  • Server Push
    • PushBuilder

JSF 2.3

  • CDI統合
    • Legacy Managed Beansは非推奨に
    • CDIのManaged Bean対応
    • より多くのJSF成果物へのInject

CDI 2.0

  • Java EEコンテナの外部でCDI動作定義(Java SE上で動く)
  • ^ のために仕様の分割
    • Core, for Java Se, for Java EE
  • 非同期イベント
    • Producer側で.fireAsyncをたたく、Observer側は@ObserveAsync

Bean Validation 2.0

  • Java SE 8サポート
    • Date/Time APi
    • Optional
    • アノテーションの繰り返し
      • 従来はコレクションを使っていたが、同じアノテーションを併記できる(Java SE 8による
    • コレクション要素への制約適用
      • 型パラメータに対してアノテーションをつける
  • 組み込みアノテーションの追加
    • @NotEmpty
    • @NotBlank

Security API for Java EE

  • セキュリティ周りの標準化
  • Authentication Mechanism
    • アプリケーションがアクセス可能な認証機構
    • 従来: 各APサーバや3rd partyの実装を用いる
  • Identity Store
    • アプリケーションがアクセス可能なアイデンティティストアの標準化
  • Security Context
    • プラットフォーム・スコープのセキュリティ・コンテキストの標準化

wrap-up

  • 今まで欠けていた部分を補い、Java EE 9に向けてポータビリティの強化が図られている
    • Cloud Platformを見据えた対応

MicroProfile 背景と意義、そしてこれから

  • @kkzr https://www.slideshare.net/kenjikazumura/
  • MicroProfile.io
    • 複数ベンダーによるEnterprise Javaのアーキテクチャ
    • ゴールはStandardization

Java EEではだめなのか

マイクロサービスアーキテクチャ(MSA)

  • 疎結合なサービスの集合体
  • 意思決定とビジネスの速さを実現するための”手段”
    • フィードバックループ(いわゆるOODAループ)による進化

MSAレイヤーと構成技術

  • アプリケーション
    • サービス分割、ステートレス、API
  • アプリケーションサーバー
    • REST, 非同期, memory footprint
    • MicroProfileはこの辺
  • VM/コンテナ
    • docker, IaaS, サーバレス

Java EEのProfile

  • Full Profile / Web Profile
  • Java EEにProfileを追加できるのはOracleだけなので、ここにMicro Profileを追加するのはOracleの判断が必要

Java EEの状況

  • J2EE 1.2 ~ Java EE 7まで、リリースの間隔はだんだん延びている
  • Public Review から Final Releaseまで、結構時間がかかるが、Java EE 8はまだPublic Reviewに到達していない
  • 2016/03の段階で、主な仕様はEarly Draft Reviewか、そこに到達していない状態
  • GlassFishのissuesは、V4以降はcreated/resolvedは少なくなっている
    • マイクロサービス、クラウドの進歩は早いが、このGlassFishの開発状況でついて行けるのか?
    • “Java EEが悪い”のではなく、”JCPのプロセスが悪い”かもしれない(アジャイル的ではない

仕様が先か、実装が先か

  • 仕様を先に決めるアプローチ(JCPのアプローチ)
    • Pros: 公正な議論、複数実装による適切な競争(よーいドンで実装着手できる
    • Cons: 仕様策定に時間がかかる
  • 実装を先に作るアプローチ(Linux Kernel等のアプローチ
    • Pros: イノベーション向き(変化が早い
    • Cons: 誰がどこで仕様を決めるか不明

JCP vs OpenJDK

  • JDKの側面
    • Java SEのRI
      • JCP, JSRによる開発
    • JDKのOSS
      • openjdk.java.net, JEPによる開発
    • JCPから見ると、JSRで決まっていないJEPの仕様が(なし崩し的に)JSRになってしまう > 議論されない
  • MicroProfile
    • MicroProfileの仕様が(最終的に)Java EEの仕様になる(といいなぁ
    • OpenJDKに基づいて別のJava SE実装を作るのは難しく、競争が起きにくい
    • MicroProfileははじめから競争を起こす前提(マルチベンダによる開発)

MicroProfile #とは

  • 2016.06に設立
    • RedHat, IBM, Payara, LJC, SOUJava等
  • 2016.09 JavaOne でVersion1.0リリース
  • 2017.01 富士通が参加
  • 2017 2Q Ver1.1(plan)
  • 2017 3Q Ver1.2(plan)

  • APSベンダーがMicroProfileを提供 > 市場が評価 > [OK]JCPへ提案, [NG]フィードバックを反映

  • アジャイル的にOODAループを実践して、最終的にJCPへ提案する

MicroProfile 1.1

  • 1.0は、JAX-RS、CDI、JSON-P
  • 1.1は、2017/2Qリリース予定
    • Configuration API
    • Health Check API
    • JWT Token Definition
    • Fault Tolerance
      • stretch goal: できなければ次のリリースで

Configuration API

  • 設定の外だし
    • 別環境への移動など、設定変更でリビルドを不要にする
  • 設定の動的反映
    • Netflix/archaiusの考え方
    • 環境変更のたびにリデプロイを不要に
      • 接続先URLの変更など(DBが死んだから切り替える、とか)
  • 優先度付けされた複数の設定(ConfigSource)で構成
    1. システムプロパティ
    2. 環境変数
    3. 設定ファイル(META-INF/microprofile-config.properties)
  • Apache DeltaSpike由来のAPI
    • メソッドベース
    • アノテーションベース
      • @Inject @ConfigProperty ConfigValue<Integer>

Interoperable JWT RBAC

  • OpenID ConnectベースのRole Based Access Control
  • 認証/認可
  • まだ具体的な仕様は少ない
    • JSONのフォーマットはあるがAPIがまだ進んでいない
    • Priority高いはずだが・・・

Service Healthchecks

  • アプリケーションのヘルスチェックをするRESTエンドポイント仕様
  • Kubernetes health check互換
  • チェック対象のアプリケーション(Producer)で、Health Check Procedureを定義(複数可)
    • すべてのProcedureがUpならUpを返す
  • GET /health > 200 Up or 503 Down
    • Procedureの結果をJSONでまとめて返す
  • (たとえば)JAX-RSのリソースで、@Healthをつけて、HealthStatusを返す

Fault Tolerance

  • アプリケーションの実行論理と、実行時のエラーハンドリングの分離
  • RetryPolicy, Fallback, CircuitBreaker, BulkHead, Timeout
    • RetryPolicy: 条件(.retryOn)、間隔(.withDelay)、回数(.withMaxRetries)を指定
    • Fallback: RetryPolicyを指定して、リトライに失敗した際の処理(.withFallback)を指定する
    • CircuitBreaker: NetflixのHystrixインスパイア
      • closed: 正常稼働
        • 何度か失敗すると(10回中3回など)、open状態に遷移
      • open: リクエスト送信遮断
        • 一定時間後に(1分など)、half-open状態に遷移
      • half-open: リクエスト送信を再開
        • 指定回数成功したら(5回など)、closed状態に遷移
        • 指定回数失敗したら(5回など)、open状態に遷移
      • メソッドAPI、アノテーションAPI

BulkHead

  • 処理毎に個別のスレッドプールを使用することで、異常時の影響を極小化したい

Timeout

  • リクエスト先がハングした時など、タイムアウトを指定しておく

サマリー

  • MicroProfileは、フィードバックループによるマイクロサービスのオープンなイノベーションを実践
  • 実装(ベンダー)を選択可能
    • アプリケーションのポータビリティを担保
  • 最終的にはJCPで標準化を目指す
    • 既存のJavaコミュニティを分裂させるものではない
    • Javaの特徴の1つである”互換性”は損なわない

質疑

  • 実装は早くても、Java EE 8とMicroProfileが両方存在する状態(HTTP/2とSPDYのような)になり、きれいなループが実現できないのでは?
    • 確かに、MicroProfileの方向とJava EEの方向が違ってくる可能性はある。しかしMicroProfileのメンバーはJCPにも参画しているので、方向性を合わせるような動きがあるのではないか。
      ※危惧としては、確かにあるので、努力していく

#jjug_ccc #ccc_r15 JJUG CCC 2014 Fall 参加レポート / R1-5 JavaでやってみるThe Twelve-Factor App

※この投稿は、丸太式 Advent Calendar 2014の6日目です

昨日に引き続き、JJUG CCC 2014 Fallの参加レポートです。

概要

R1-5 JavaでやってみるThe Twelve-Factor App
by 渡辺 祐さん(株式会社ビズリーチ)
@nabedge

メモ

The Twelve Factor App

  • 論文(っぽいよみもの)
  • Herokuの元CEOが作った
  • “どんなWebアプリケーションであっても、だいたいこの方針で作ればいいんじゃねーの”というもの

ポートバインディングを通じてアプリケーションを公開せよ

  • 【自らポートを開いて】
    • 開発したアプリケーションの”依存ライブラリのTomcat/Jettyで”ポートを開く
  • main()メソッドで起動できるので、Run As -> Java ApplicationでTomcatがポートをバインドして起動できる
    • WTP Plugin, Sysdeo Tomcat Pluginはいらない
    • Tomcatのバージョンアップも、pom.xmlのバージョンを変えれば良い→普通のリリースフローで対応可能

廃棄容易性

  • 高速な起動はJavaではあきらめる
  • グレースフルなシャットダウン: Shutdown Hookを使う
    • Springなら@PreDestroyアノテーションをつけるとシャットダウン前に呼ばれる

ログをイベントストリームとして扱え

  • 「全てのログを標準出力に集める」
  • とりあえず標準出力に出しておけば、後から好きなところに流せるので。
  • 依存ライブラリのログ出力はslf4jのブリッジライブラリなどで集約する
  • GCログは・・・

設定はOS環境変数に格納せよ

  • 設定ファイルに本番DBのパスワードも格納してVCSに管理するの?
  • OSが違っても環境変数の設定はほとんど同じ
  • 気の利いたライブラリはOS環境変数からの設定値読み込みは対応している
  • 今時ならChef/Puppet/Ansibleで設定するでしょ

依存関係を明示的に宣言し分離せよ、ビルド/リリース/実行は厳密に分離せよ

ビルド

  • バイナリ間の依存関係管理機能のあるビルドツールを使う(Maven, Gradle)※Antはダメよ

  • ビルドの結果はjar, warというバイナリ

  • バイナリはパッケージリポジトリサーバにデプロイするもの
  • MavenもGradleも、依存関係の解決にはパッケージリポジトリを使う

リリース

  • パッケージリポジトリから開発したアプリのJARと依存ライブラリのJARを取得して、依存JARをコピーしてZIPに固めてSCPで送り、サーバー上でUNZIPするまで

実行

  • java -cp “jar群の展開dir/*” com.example.ExampleMainClass
  • 設定は環境変数に格納されているはず

アプリケーションをステートレスなプロセスとして実行せよ

  • 少なくとも、Stickyセッションを使うな→現実問題難しい
  • ステートレス:アプリケーションサーバにセッションを持たせない

#jjug_ccc #ccc_r13 JJUG CCC 2014 Fall 参加レポート / R1-3 実例Javaトラブルシューティング! 稼働中のシステムを立て直した半年間の軌跡

※この投稿は、丸太式 Advent Calendar 2014の5日目です

11月15日に、JJUG Cross Community Conference 2014 Fallが新宿で開催されました。
朝の基調講演から参加するつもりでしたが、残念ながら寝坊してしまったので途中からの参加となりました。
今日から何日かに分けて、セッションのメモをAdvent Calendarの記事として公開していきます。

概要

http://www.java-users.jp/?page_id=1292#R1-3
by 谷本 心さん@Acroquest Technology(株)
@cero_t

メモ

世の中のシステムは完璧か?
→最近リリースしたシステムは完璧か?

完璧ならざるシステムの例

処理が遅い
アクセスを裁けない
脆弱性
システムエラー
etc…

方針

  1. 検索処理の高速化
  2. 購入エラーの是正
  3. 大量アクセスを捌く
    ※Struts + Hibernate + JSP

最初にやったこと

→まずはSeleniumの自動試験を作る
直す過程で壊すことがないように
→CheckStyle / FindBugsをかけてリファクタ
可読性を向上させながら、何とかする

→ダメだった。
1. 300KLのコード、大半がデッドコード
1. 試験項目作成中にもエラーが頻発
1. その間にも本番システムでエラーが多発

方針転換

  • 問題のトリアージ(優先度の設定)
    「一番の問題は何か?」→「購入に失敗すること」(損失の本質)
  • 購入に失敗する理由→これらの改善こそ【顧客が求めること】
    • 購入時にシステムエラーが起きる
    • 検索が遅くて購入までたどり着けない
    • TV放送でアクセスが集中すると、システムがダウンしてしまう
  • どうやって問題を見つけるか(ソースコード上の問題より、現場の問題をつかむ必要がある)
    • エラーの発生頻度(HTTPステータス、アプリケーションエラー)
    • 性能の傾向(通常のレスポンス、アクセス増大時のレスポンス性能)
  • どうやって現場の問題をつかむのか
    ※稼働システムにブレークポイントはだめ

    • ログの収集(アクセスログ、アプリケーションログ、MySQLのスロークエリログ
    • 低負荷な解析ツールの適用(ENdoSnipe等)
  • ログ分析
    • ElasticSearch(ログの蓄積) ※リアルタイム検索・解析エンジン
    • Kibana(可視化) ログ検索、可視化
    • Fluentd(収集)
  • 典型的な問題の検出
    • ENdoSnipe OSSのトラブルシュートツール。メモリリークや同一SQLの発行回数など。動的なFindBugsのようなもの

Mission1 検索処理の高速化

  • 問題点
    • 検索処理は日常的に重い(10~30秒程度)
    • 2~3日間隔で非常に重くなる
  • 分析状況
    • 100件/秒のアクセスで、全てのレスポンスが5秒以上かかる
    • 夜間、ほぼアクセスがない場合でも10~20秒かかる
    • 謎のレスポンス劣化(最大3000秒!!!)
      • スロークエリログを見ると、同じ形になる→間違いなくDBに問題
      • なぜ線形に上がるのか?→SQLを見ると、全て同じストアドプロシージャ
  • 謎のレスポンス劣化原因について仮説を立てる
    ※トラブルシューティングでは、まず問題を確認し、仮説をいくつか立ててから検証・考察するべき

  • スロークエリのストアドプロシージャを精査

    • Temporary Tableに数万件のinsert
    • 明らかに無駄な処理が多数あり、削ったが改善されず
    • Temporary Tableはどうしても必要だったので、
      • Temporary Tableをon memory
      • Temporary Tableのメモリ割り当てを増やす
        →結果・・・Disk I/Oが激減、CPUのI/O waitが激減。スロークエリも改善

Mission2 購入エラーの是正

  • 問題の確認
    • 購入処理の途中でエラー
      • システム内要因(NPE等)
      • 外部システム要因(DB,決済等の応答無し、等)
    • お客様からのクレームで気づく
    • カード決済が絡むので、問題
  • アプローチ
    • 購入処理の開始時にロギング(ログをDBに記録)
    • 処理の途中、終了時にもロギング
    • ログを解析して、正常終了した処理と異常終了した処理を可視化
    • エラー原因ごとに発生件数を整理して、件数が多いエラーから順に対応
    • バグパッチを当てるたびに、エラー数が半減
    • 外部システム要因のエラー以外は対処完了

Mission3 大量アクセスを捌く

  • 問題
    • TV放送などで大量アクセスがあるとレスポンスが悪化してシステムダウン
    • ストアドプロシージャは対処したが、CPU使用量は上がるので。。。
  • アプローチ
    • 同時アクセス数制限の強化 APサーバごとに、検索処理の同自利楠と数が一定数を超えたら503
    • 検索結果のキャッシング
    • 同時検索数を制限 ※同一検索条件は待たせ、キャッシュから読み取る。違う検索条件では同時に検索できる仕組み
  • 構成の問題
    ボトルネックはDBなのに、なぜAPサーバをスケールアウトしているのか・・・
  • アプローチ
    TV放送時にもスケールアウトしない
    →システムダウンがなくなる
    →レスポンス改善
    ※closeされていないコネクションが残ってしまう場合があった

このシステムの今後

  • 全面的なデザインリニューアルと同時に処理をRESTful APIとして再実装
  • 購入処理の非同期化
    • 在庫確保とカード決済ができた時点でレスポンスを返す
    • 外部システム連携部は自動リトライ
  • ElasticSearch / Kibanaの改善
    • シングルノードで運用しているので、たまに死ぬ
    • 処理負荷が高すぎて過去ログを流し込めない

まとめ

  • 長期的トラブルシュートでは、ログの可視化は効果的
    • 現実に起きている問題がわかる
    • 改善効果がわかる
  • 下手にスケールアウトすると怖い