そもそもJWTに関する私の理解は完全に間違っていた!
TL;DR
- ステートレスなJWTはそもそもセッションの代替では無い
- アクセストークンとしての利用が基本で数分レベルの短寿命な有効期限で利用
- 従来のセッションに近い概念はリフレッシュトークン。てか、リフレッシュトークンはセッションでも(たぶん)良い
- ユースケース的にモノリスには不要。SPAでMSAな時にメリットが出て来る。
はじめに
Webで認証システムといえばセッション! と言う感じのレガシーおじさんなのですが、最近はJWTとかも出てきてとても気になっていました。新しいものは使ってみたくなりますよね?
なので以前軽く調べてみたたのですが「JWTは危ない」とか「JWTをセッションに使うな」的な記事が大量に出て来ます。
一方で反論記事もあり色んな議論が渦巻いています。そもそも利用を推奨する記事も多い。
この辺りで「JWT怖い!」となり、状態を結局サーバで管理しないとセキュアに使えないならメリットは一体? とも思って一旦放置してたのですが「リフレッシュトークンとアクセストークンに分けて考えるのが前提」と言うのを下記の記事で理解してスッキリしました。
といわけで、私ので理解があってるかの確認がてらまとめてみました。
たぶん私と同じくユースケースが理解出来てなくてイメージが出来なかったり過った利用方法をする人も居ると思うので、そもそも何で必要なの? ってところを重点的に書いてみました。
実際にJWTをまだ使っては無いので理解が過ってるところがあれば指摘いただければと思います。
そもそもセッションにJWTを使って良いの?
「ダメです」
特に、JWTのメリットとして語られるサーバサイドで状態管理しなくて良いから云々でセッションの代替として使うのはアンチパターンと思われます。
そもそもセッションとは状態管理です。その時点でステートレスなインフラを作るのは難しくクライアントサイドでの管理はリスクがあります。幻想は捨てましょう。
ただし、JWTをアクセストークンとして使う事で今まではセッションで実現していた事の一部が代替できます。それは「認証」です。
そもそもセッションがなぜ必要?
さて、そもそもセッションはなぜ必要でしょうか? Webで言う「セッション」とはステートレスなプロトコルであるHTTPにサーバサイドで状態を持たせる仕組みの総称です。
元々は論文などのドキュメント公開の仕組みとして作られたHTMLとHTTPは状態が必要に無いのでその仕組みは存在しません。しかし、ひょんな事からWebアプリケーションとして様々な事に利用されるようになっため状態を持たないと都合が悪いケースが増えて来ました。
その流れでクライアントサイドに情報を保存するCookieなども登場し、クライアントとサーバで共通のキーを持ちそのキーにサーバサイドで情報を紐付ける「セッション」が実現できるようになりました。
「セッション」を使う事でユーザがログインしているかを判別してユーザ毎の情報を表示するなどの状態をベースにしたWebアプリケーションが作れるようになりました。
セッションのストレージには色んなものが試されていて「NFS + ファイル」「RDB」「インメモリ」「KVS」とかありました。現在の主流はKVSでしょう。JavaEE系はインメモリも現役ですね。
歴史があるだけあってこのCookieとサーバサイドのストレージを使ったセッションはセキュリティ的にも運用的にもかなりの積み重ねがあります。そのため安心して使えるのですが問題ももちろんあります。
ステートレスアプリケーションとスケールアウト
サーバが3台とか5台くらいなら割となんでも良いのですが、サーバをスケールアウトして30台とか100台でWebアプリケーションを実現しようとすると、セッション用ストレージのインフラを作るのが結構骨です。
その流れで普及しだしたのがステートレスアプリケーション。RESTとかROAとセットで語られることが多かったと思います。
ざっくりと言えば「セッションを使ったアプリケーションはスケールさせるのが大変だから情報をクライアントに持たせて全部リクエスト毎に付与しよう」と言う考え方です。
これならサーバに状態を持たなくて良いからストレージがSPOFやボトルネックになる事も無いわけです。なので基本的な考え方になって行くわけですが、この考え方がだと送られてくるデータを全部信用するしか無いわけです。
そもそも渡されるu_idを自由にクライアントが指定できるのでなりすまし天国です。なので、バックエンドAPIとしての利用が限界でそれも「信頼されたアプリケーションから送られて来た情報は信頼する」と言うのが前提となっているので少し弱い。
マイクロサービスとSPA
色々あってマイクロサービスが流行ります。これをサーバサイドでアグリゲーションして一つのWebページとして返してる分にはあまり問題が無いのですが、SPAとかでクライアントサイドでアグリゲーションする場合は問題です。
流石にクライアントサイドからの情報を無条件に信用するステートレス実装はできません。なので、セッションなどを使ったステートフルな実装が基本になるかと思います。その場合はセッションのチェックが1ページ見るのに5個も10個も走る事になります。
今時はインメモリ実装かKVSなのでそこまで一つ一つは大きなコストでは無いですが無視できるものでも無いはずです。特にマイクロサービスだとインメモリは不可能なので必然KVSになります。負荷の集中もそうですが、マイクロサービスなのに共通のストレージにアクセスするのは正直筋の悪い設計となってしまいます。
この辺はエアプなので想像ですが、たぶんこう言う問題は起こるはずです。
ソーシャル・ログインとAuthorizationプロトコル
少し違う文脈としてソーシャル・ログインの台等とそれを支える技術であるOpenIDから始まりOAuthを経てOIDCに辿り着いたAuthorizationプロトコル群があります。
以下のブログでも書きましたが、もはや自前で認証機能を作るのはリスクの観点で可能な限り避けるべき事なので、GoogleやTwitterといった信頼できる認証システムをOAuthやOIDCで使うのが一般的です。 koduki.hatenablog.com
これらの認可プロトコルでは必然的に認可の基盤と実際に利用されるアプリケーションが異なります。その為ものすごく素朴に実装すると毎回認可サーバに問い合わせます。
これはインターネット越しだとそれなりのレスポンスになるはずなのでなんとかしたい。。。と言うわけでこの手のプロトコルの仕様を決める際に寿命の長いリフレッシュトークンと短いアクセストークンに分ける考え方やステートレスに認証できるJWTも作られた見たいです。
リフレッシュトークンとアクセストークンを利用した認証
さて、前置きがとても長くなったけどようやく本題のリフレッシュトークンとアクセストークンのお話。
マイクロサービスとSPAのところでした説明した図を思い出して欲しいのですが各サービスではクライアントの情報は信用できないのでサーバサイドで管理する必要があリマス。逆転の発想で「クライアントからのリクエストが信用できればサーバでの状態管理は不要」となります。
「ユーザID」や「どの機能アクセスできるか等の権限」といった情報を信頼できるサーバで秘密鍵により電子署名を付与する。APIサイドでは公開鍵を使って改ざん検知をするだけで渡された情報を信用できるのでストレージにセッション情報を保存する必要はない。これがアクセストークン。
では、信頼できるサーバとは何か? そもそもクライアントで秘密鍵を使って署名を付けてもオレオレ証明書なので信頼性はない。なので、第三者の認可サーバを使う。ここでユーザIDとパスワードだとかMFAだとか良い感じにユーザを認証してその証明となるキーを発行する。これがリフレッシュトークン。
リフレッシュトークンを持ってるクライアントが認可サーバに必要な情報を渡して署名付きのアクセストークンを作るという流れです。
JWTは署名付きで任意のペイロードを持てるのでステートレスなアクセストークンの実装に最適という話。そしてリフレッシュトークンはステートフルが要求されるのでJWTを使う意味はあまりないはずです。
自分で実装するならリフレッシュトークンはトラディショナルなCookie + サーバサイドなセッションがWebアプリは一番楽かもと思っています。
JWTとセキュリティ
さてステートレスなJWTは実際セキュアだろうか? これは実装次第だけど基本的には問題ないと思います。
当たり前ですがJWTであるアクセストークンは改ざんチェックしかしてないので本人認証としては弱い。なんらかの問題で流出したらアウト。秘密鍵を変えるか有効期限が過ぎるのを待つしか無いです。
たとえリフレッシュトークンを使って再発行しても古いアクセストークンをステートレスに無効にすることは出来ない。やるならブラックリストデータを状態として持つしかない。
なので理想的にはアクセストークンはワンタイムトークンとして振る舞うのがセキュリティ的には良いと思います。仕様上それは出来ないから1分以下とか超短期の有効期限にするのがベスト。
これならアクセストークンが流出してもあまり問題はないはず。リフレッシュトークンはサーバサイドで状態を持ってるので万一流出したら破棄することが出来るので通常のセッションと同程度の長さで問題はないし明示的なログアウトも作れます。
ただし、アクセストークンの有効期限が短いと認可サーバへの問い合わせ回数が増えるのでここはトレードオフですね。認可サーバの負荷的には従来のセッションによると大差無い気もするけどクライアント側の通信コストが問題。ユーザが多いと署名コストもボトルネックになるかもです。
この辺のさじ加減は作ってみないと分からないのでバランスはサービス次第になるかと思います。
JWTはセッションの代わりになるのか?
なりません。
セッションが担っていた一部である認証に関しては限定条件で効果的に果たせそうです。ただ、そもそも状態の保存ができません。「ペイロードに格納すれば良いじゃん?」って話ですがそれは都度都度アクセストークン発行すれば出来ますが、たとえばAmazonの買い物カゴみたいなのをJWTで作るのはかなり面倒では。
その場合は大人しくCookieやLocal Storageに格納してAPIのBodyに入れるのが良いかと思います。暗号化もサポートしてるけど多少センシティブなものも突っ込めそうですが、ストレージとしての用途を考えて作ってるとは想定しづらいのでセッションの単純置き換えは無理でしょう。この点に関してはそう思ってる人も多分居ないと思いますが。
まとめ
さて、思ったより長かったけどJWTを使った認証の流れとユースケースを私なりにまとめてみました。
何というか従来的なモノリスなアプリケーションだと何ら意味が無いという事が分かった。
セキュアに作るならステートフルなリフレッシュトークンとステートレスなアクセストークンにする必要があり、単独アプリならステートフルなトークンすなわちセッションだけで十分だし。ソーシャルログインとか別の仕組みの一部として使う分には別だけど。
ここを理解しないとJWTをセッションに使おうという発想になってしまうのだろうなぁ。とは言え私の今の理解が正しいとも限らないけど。認証周りは本当にややこしい。。。
それではHappy Hacking!
参考
Graphvizで画像を読み込むとエラーになる
Graphvizで画像を下記の構文で読み込もうとするもビルド時にエラーが発生。
d [shape=none, label="", image="sample.png"];
$ dot -Tpng -o sample.png sample.dot Wed Oct 30 23:03:17 2019 2019-10-30 23:03:18.988 dot[97555:3328824] +[__NSCFConstantString length]: unrecognized selector sent to class 0x7fff9f6133a0 2019-10-30 23:03:18.988 dot[97555:3328824] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[__NSCFConstantString length]: unrecognized selector sent to class 0x7fff9f6133a0'
どうもbrewでインストールしたGraphvizにlinbpngとかが適切にリンクされてないのが原因っぽい。と言うわけで以下のコマンドで再インストール。
$ brew uninstall graphviz $ brew install pango librsvg $ brew install graphviz --build-from-source
これで無事画像が表示されるようになる。
個人的に気になってるNewSQLな一覧
OceanBaseとかNEDOに採択されたProject Tsurugiとか気になるニューフェイスが登場したので、トラッキング用にメモしておく。 NewSQLの定義が謎だけど、たぶん脱レガシーを標榜したSQLは皆NewSQLに分類されてるんじゃ無いかなぁ?
OceanBase
- Alibabaによって開発/実用されているRDB。暫定世界最強。
- SSDなどの最新のHWを前提にした構造。書き込みに強い
- MySQL互換
- 詳しくは下記 koduki.hatenablog.com
Project Tsurugi
- NEDOに採択された日の丸RDB
- PostgreSQL拡張?
- 現代のメニーコア/SSD/不揮発性メモリを前提に設計したインメモリDB.
- 分離レベルがSerializationなのに書き込みも含めて高速!?
- 以下参照
PG-Strom
- GPUを活用してスケールアップを目指したPostgreSQLベースのDWH。OLAP向け。
- JOINやSCANをGPUにオフロードすることで大幅な性能を向上
- SSDからRDMAで直接GPUに転送してるので圧倒的なI/Oを誇る。
- 以下参照
VoltDB
- ストアドプロシージャのみをサポートしたインメモリDB
- ACIDを保ちSQLを持ってもKVS並みの速度は出るとか言い出した先駆者。速いらしい
- ロックフリー。水平スケーリング
- 現代ではインタラクティブなSQLをアプリケーションで投げるとかレアなので割と有りかと思える面白いデザイン
- 国民的アイドルの総選挙を支えたことでも有名
- 以下参照
Peloton
- The Self-Driving Database Management System
- Oracleと同じ定義なのか含めてちょっと気になる
- 以下参照
CockroachDB
- Cloud Spannerのクローン版。原子時計が無くても動く
- 名前とアイコンがひどい
- 以下参照
まとめ
自分で書いたことはもちろん利用者としてもDBに詳しいとは言えないけど、DB系の説明は読んでてワクワクしちゃうのでつい追っちゃうんですよね。
もちろん、HANAとかAWS AuroraとかCloud SpannerとかExadataやNonStop SQLとか商用にも興味深いのはいっぱいあるのでだけど、とりあえずマイナーそうなのを忘れないように上げてみた。気になったのが増えたら追加するかも。
しかし、SpannerのクローンはあるのにAuroraのクローンは無いのかな?S3にログ書くデザインとかCloud前提であれも面白そうなんだが。
それではHappy Hacking!
世界1位になったアリババの独自開発DB OceanBaseとは何者か?
さて、1週間くらい前のニュースですがAlibabaがOracleのデータベースを抜いて世界1位の座を獲得しました。 itnews.org
世界一位って何よ? って所なのですが TPC-C - All Results - Sorted by Performance の結果みたいです。
まあ「Oracleのデータが10年前の11gなので今のExadata X8Mとは比べ物にならない程性能が低いであろうこと」「HPEとかも虎の子のNonStop SQL出してない」「レギュレーションの問題なのかやる気の問題なのかAWS AuroraもGCP Spannerも居ない」という事もあって、最速のRDBランキングとしての妥当性に疑問はありますが、これはランキングが悪いのであってAlibabaを貶めるものでは無いでしょう。誇大広告感は狙ったと思いますがw
ベンチマーク結果としては以下のように、2位のOracleと比較して性能がザックリと2倍。ただしコスパは10%ダウンです。とはいえ当時円高だった事もあって同等といっても差し支えは無いでしょう。
DB | System | Performance (tpmC) | Price/tpmC |
---|---|---|---|
OceanBase | Alibaba Cloud Elastic Compute Service Cluster | 60,880,800 | 95.6 円 |
Oracle | SPARC SuperCluster with T3-4 Servers | 30,249,688 | 84.2 円(当時) |
どんなデータベース?
Database of Databases - OceanBaseによると2013年から開発されていて以外と実績がある事がわかります。GithubにソースコードはGPLで公開されていますがほとんど更新されていません。現状の最新版の2.0とはかなり変わってるかもです。
我々が普通に使おうとするとAlibaba Cloudを利用するしか無いっぽいですね。
公式ページや中国語の解説サイトをGoogle翻訳しながら調べた感じだと以下のような特徴があります。
- 伝統的なRDBのACIDやSQLとNoSQLの可用性やスケーラビリティを備えたデーターベース
- SSDなどの最新のハードウェアを前提として設計
- Shared Nothingな分散DB
- マルチリージョンなどクラウド環境を想定したアーキテクチャ
- MySQL互換
- LSM treeのような階層的なストレージ構造により高速なDMLを実現
この点としては割と現代的な分散DBあるあるな特徴ですね。Auroraとか。
ストレージエンジンなんかは結構面白そうな特徴を持っていました。 ref: OceanBaseの概要 - ストレージエンジン
データをまずIncremental Data(増分データ)とHistorical data(ベースライン)に分けます。その上で、増分データはインメモリ(MemTable)、ベースラインはSSD(SSTable)に分けて保存します。
RDBで良く使われるB-Tree Indexは原理的にReadには強いけどWriteには弱いという特徴を持っています。これはリアルタイムにインデックス全体を再構築するためです。増分データとベースラインを分けることでWriteが発生した時の作業範囲を小さく出来ます。で、実際にデータを見るときにはSSTableにMemTableの差分を適用して見ることで対応してるかと思います。
また、SSTableは常にRead Onlyなのでロックは不要。増分が書き込まれるMemTableもRead時はロックフリーとの事なのでイベントログ自体を書き込んでると思われます。
LSM treeそのものを使ってるかはちょっと分からなかったですが、マージコストをLevelDBやRocksDBと比較してるので似たような考え方などだと予想。
結果として、DMLは全てメモリ操作になるのでインメモリDB並みに高速なようです。
Ali Payとかにも使ってるなら書き込み性能が参照性能以上に重要になって来るので、その辺りを重視した設計になってるのでしょうね。
まとめ
分散トランザクションとか色々書いてあって面白そうなのですが、良く分からないのでデーターベースに詳しい人が誰が解説してくれるのを期待!
あと、日本語はもちろん英語のドキュメントすらほぼ無いのが最大の欠点ですね。その気があれば上手く英語化したりグローバルにもオープンにしていく事で、ひとかどのポジションを気づくかもです。
しかしRDB自作できる会社は強いですよねぇ。日本だと今や日立くらい? KVSは結構各種Web企業も一時作ってましたが。
TPC-Cに関しては恐らくAmazonにAWSに全面移行された記事とか合わせてイラっとしてるOracleさんが、大人気なくベンチマークを更新し他社もそれに乗ってきてそれなりに意味のあるランキングになるとちょっと面白いなぁ、と個人的には思います。
参考
JDK Flight Recorderのアーキテクチャ概要
はじめに
JDK Flight Recorder(JFR)はJavaで利用できる常時本番適用可能な超低オーバーヘッドのプロファイラです。性能分析とか障害対応の強い味方ですね!
今まで商用ライセンスのみ使用可能だったのですが、JDK11よりOpenJDKに取り込まれ自由に使えるようになりました。オープンになったので色々自分でも使いたいですし、色んな人にも使って欲しいなと思っています。
ただ、Oracleの公式ドキュメントが余りにもサラリとし過ぎていて良くわかんないので、いくつかのOracleや有志の発表資料や自分の知識を元にアーキテクチャ概要を解説して見ました。
この辺をしっかり分かりやすく書いた公式ドキュメントが無い(=あればそれが欲しい!)のと、ソースコードまで読んだ訳では無いので普通に間違ってる箇所がある可能性があります。詳しい方いましたらぜひ指摘して頂けると嬉しいです。
JFRにおける「イベント」
JFRはプロファイリング/診断のためにイベントを集めるメカニズムです。
イベントとはJVMまたはJava アプリケーションから取得するデータで、「名前」「タイムスタンプ」「カスタムペイロード」を持ちます。こちらのペイロードが実際の性能情報等が書き込まれる部分で、CPUの情報とかヒープだとかスレッドだとか具体的な値が格納されています。
主として下記のような情報が取得できます。
取得対象 | 主な取得内容 |
---|---|
オペレーティングシステム | メモリ、CPU Load、CPU情報、ネイティブライブラリ、プロセス情報 |
JVM | メモリの割当て、クラスのロード, JIT, GC, メソッドプロファイルイベント |
Java API | ソケット I/O, ファイル I/O, 例外、スレッド、モジュール情報 |
カスタムイベント | アプリケーションコンテナなどのミドルウェア、その他ユーザ定義イベント |
アプリケーション、JVM、OSと広範囲に情報が記録される事がわかるかと思います。また、カスタムに関しては下記のように作成/利用が可能です。
public class HelloJFR { @Label("Hello World!") static class HelloWorldEvent extends Event { @Label("Message") String message; } public static void main(String[] args) { HelloWorldEvent event = new HelloWorldEvent(); event.message = "Hello World!"; event.commit(); } }
Weblogicのようにすでにカスタムイベントに対応したミドルウェアを使えばサーブレットやJDBCの情報も取得できますし、自分で拡張することも可能です。 こちらに関しては4章と6章で詳しく説明します。
イベントタイプとサンプリング
JFRでは以下の3つのタイプのイベント分類して情報を収集します。
期間イベント(duration event)
インスタントイベント(instant event)
- 期間を持たない発生すると直ちに記録されるイベントです。Exceptionなどがこれに当たります。
サンプリングイベント(sample event/requestable event)
- 定期的に記録されるイベントです。CPU使用率などがこれに当たります。こちらの頻度は変更可能です。
JFRは大量のメトリクスを格納しつつも低遅延を保つために閾値を指定したりサンプリング頻度を過度に上げない事が重要です。
多くの場合、極端に実行時間が短いイベントは問題の焦点ではない事が多いので閾値を付けるのは妥当なトレードオフだと思います。もちろん、これはアプリケーションの性質で大きく異なり、例えばバッチとリアルタイムシステムでは「遅い」という時間の基準が違うので、必要に応じてカスタマイズをします。
データフォーマット
イベントはJSONやMessagePackのような自己記述的なデータ構造です。IDLやヘッダーなどが不要になるのでイベント単位で色々加工したいログには向いたデータ構造と言えます。データもバイナリフォーマットなため非常に効率的です。
例えば、クラスロードイベントの場合、タイムスタンプ、タイムスパン、スレッドID、スタックトレース、ペイロードを含み、下記のように格納されます。
<memory address>: 98 80 80 00 87 02 95 ae e4 b2 92 03 a2 f7 ae 9a 94 02 02 01 8d 11 00 00
- Event size [98 80 80 00]
- Event ID [87 02]
- Timestamp [95 ae e4 b2 92 03]
- Duration [a2 f7 ae 9a 94 02]
- Thread ID [02]
- Stack trace ID [01]
- Payload [fields]
- Loaded Class: [0x8d11]
- Defining ClassLoader: [0]
- Initiating ClassLoader: [0]
ref: https://openjdk.java.net/jeps/328
循環バッファとデータフロー
JFRではイベントは循環バッファに記録されます。これは、メモリとディスクを組み合わせた概念で階層を持たせる事で低遅延かつ大量のデータ格納を実現しています。
循環バッファの各領域 | 説明 |
---|---|
Thread-local Buffers | 各スレッドが持つローカルバッファ領域。5KB/Thread |
Global in-memory Buffer | Javaアプリケーションで持つインメモリ領域。452KB (default) |
ディスク領域(リポジトリ) | オプション指定をして置けば溢れたデータをChunk単位に分割してダンプする。 Max Chunk Sizeは12MB (default) |
まず、JFRがJVMおよびJavaアプリケーションから集めたデータを 「Thread-local Buffers」 に格納します。ここは比較的小さめのサイズとなっています。
次に、 「Thread-local Buffer」 のデータが溢れたら、「Global in-memory Buffer」 にデータがコピーされ古いデータは破棄されます。
最後に、 「Global in-memory Buffer」 から溢れたデータは 「リポジトリ」 と呼ばれるディスク領域に 「Chunk」 の単位で格納されます。こちらはJVMオプションでdisk=true,repository={一時ファイル保存先}
を指定した場合のみに格納されます。また、ファイルに格納されるイベントは複数スレッドから集められているので必ずしも時系列順を保証はしません。
JFRのデータフローを図示すると以下のようになります。また、MaxSizeもしくはMaxAgeで循環バッファ全体の閾値を決めます。この閾値を越すとリポジトリのデータも古いものから順に消去されることになります。 図. JFR イベントのデータフロー
また、異常/正常問わずJavaのプロセスが終了すればJFRファイルとして結果を格納する事が可能です。
リポジトリとJFRファイル名
JFRではfilename
というJVMオプションでJFRファイルの格納先のファイル名を指定できます。
ただし、注意が必要なのはこれは循環バッファの内容が 順次書き込まれる場所ではない という事です。
ここは少しややこしくて、この関係性を理解していないとJFRファイルの取り扱いで混乱してしまいます。
前述の通り、循環バッファの内容はrepository
オプションで指定されたディレクトリにファイルダンプとして出力されます。もし「実行中のJavaアプリケーションのJFRファイルを取得したい」
と思うなら、リポジトリのファイルを取得してください。
filename
に出力されるのは最終アウトプットになるJFRファイルです。このファイルはプロセスの完了時かJMXまたはJMCやJCMDでJFRのダンプ命令を出した時に出力されます。そして 「プロセス完了時点またはダンプ命令時点の循環バッファ」 が格納されます。そのためプロセスが動いている間は基本的にファイルは書き込まれません。
なので「Webアプリケーションのような長期に動くJavaアプリケーションのJFRファイルをバックアップしたい」等といった用途にはリポジトリからファイルを取得してやる必要があります。おそらくこちらのリポジトリに格納される一時ファイルの方が 「ログ」としてみた時の運用には近いと思います。
また、maxsize
やmaxage
を指定した場合は循環バッファ全体の閾値となるので結果としてfilename
に含まれる内容になります。裏を返せばリポジトリに格納される一つ一つのJFRファイルのサイズはmaxsize
で指定できません。こちらに関してはmaxchunksize
を変更してやる必要があります。
両方指定することも可能ですが、個人的にはリポジトリだけ指定してれば実運用上は十分な気がします。この辺りに関しては5章で解説します。
JFRの開始とJFRファイルダンプ
JFRはMBean(FlightRecorderMXBean)またはJDK JFR Managemnet APIを使うことで操作(開始/終了)が可能です。また、JDK Mission ControlやJCMDおよびJVMオプションでも可能です。
デモなどではJMCやJCMDを使ったものを良く見ますが、実運用上はJVMオプションで指定して常に記録を行いリポジトリに格納される一時ファイルかプロセス終了時に作成されるJFRファイルを確認する事がほとんどだと思います。
まとめ
さて、ちょっと長くなりましたがこんな感じでしょうか。特に、循環バッファやリポジトリとJFRファイル名の事は把握しておいた方が実運用でも便利です。
コメントまたは指摘等を頂けるととても嬉しいです。
それではHappy Hacking!
参考
Oracle Code One 2019に参加してきました
ブログに書くの忘れてましたが、去年に引き続き今年もOracle Code One/Oracle Open Worldに参加してきました。
すでにキーノートとかの詳細は素晴らしいレポート出てるのでそちらをみてください。
- Oracle OpenWorld 2019開幕 - エリソン氏が数多くの新製品を発表 (1) ラリー・エリソンが「Gen2 Cloud : Autonomous Infrastructure」をテーマに講演 | マイナビニュース
- Oracle Code One 2019速報レポート:レポート|gihyo.jp … 技術評論社
あと、去年とは違いありがたいことに今年は採択されたので発表することができました!
Performance Monitoring with Java Flight Recorder on OpenJDK [DEV2406]
話したいところはある程度気持ちを乗せてちゃんと話せたかなと思う反面、質疑応答はもう少しスムーズに出来たらとも思ったのでやはり英語の練習をもっとしないとですね。
で、ここからはかなり主観というか個人的な想像を入れた気になるトピックのまとめです。
JDKの新機能と進捗
ここに関しては良い意味で新しい情報は無かったです。OpenJDKがOSSとして運用されJSRやJEPでオープンに仕様が管理されているので、Oracleが隠し球で持ってた新機能の発表とかは無かったです。
カンファレンスに行って目新しい情報が無いというのもちょっと寂しいですが、AppleはオープンソースのはずのSwiftでそれをやらかして炎上しましたし、OSSとしては健全なのでこのほうが良いですね。
もちろん、各機能のJEPの現状や詳細機能の説明はとても参考になりますし、クォータリリースなので1年間を振り返ったサマリーは役に立ちます。
GraalVM
反面、ロードマップを含めて色々発表があり注目の的だったのがGraalVMです。
GraalVM自体は去年も発表ありましたし、結構前から存在していますが1.0になったということもあって今年はかなりアピールしていました。
native-image(AOT)を中心にコミュニティからの発表も多かったですが「OpenJDKと互換性を保ったまま高速なJVM(JIT)」としてOracleがかなり強く推してたので、おそらくGraalVM EEを結構推していきそうな感じです。OCIなら無料というのも売りにできるでしょうし。
ちなみに価格表を見るとOracle Java SE($25/processor/month)よりGraalVM EE($18/processor/month)のが安いので、OracleJDK使うならGraalVM使えよ、というオーラが出まくっていますw
あと、ロードマップ的には11月にはちゃんとOpenJDK11に対応するので、少なくともLTS版には随時追従していく形になるのだと思われます。 思ったよりOpenJDK11対応が早くて安心。
AOTやマルチ言語対応もかなり進んでてLLVM組み込みはJNI代用として面白そう。あと、Rubyもほぼレディな状態になっていて後はバージョンを追いつかせるだけ、とのことなのでここも個人的にはかなり気になります。爆速だし、JFR使えるかもだし。
なおAOTとJITは現時点では以下のような性能のトレードオフがあるけど、将来的には全部AOTで上回りたいという野望があるそうですw
Jakarata EEとEclipse MicroProfile
大変悲しいことですが今回のタイミングでJakarata EEにMicroProfileは統合されませんでした。
名前空間の差分とかの話もあるのですが、そもそもマイクロサービスの早い進化に対応させたいMicroProfileと標準化を主眼としてるJakarata EEではライフサイクルが異なるという問題も大きいようです。
個人的にはLTS版的な感じて定期的にJakarataEEにMPの仕様が取り込まれれば良いと思うのですが、今のままだとSpring的なポジションになる可能性もあってちょっと心配。 たぶんJakarataEEで行われるであろう名前空間の変更と合わせてMPの取り込みも来年か再来年くらいにされるんでは? 的な雰囲気なので当面はMPが実質的な仕様を牽引してく形になりそうなので、こちらを追う感じですね。
MPに関してはOracleもWeblogicではなくHelidonで対応していくとJakarataEEのセッション中に言ってましたし、IBM RedhatのQuarkusと合わせてエンタープライズのサポートも問題なさそうです。
MPとしてはやはり話題の中心はnative-image + QuarkusでWebSphere LibertyやPayara Microはあまりトピックにはなってなかった印象。もちろん、ユーザ事例として出てくるときはそれら既存の奴を使ってたでしょうが、あまりその手のセッションは参加しなかったのでちょっとバイアスあり。
ただ、native-imageとの連携もあるので既存のアプリケーションコンテナとしての実装ではなく、Helidon/QuarkusのようなMP向けライブラリとしての開発が主流になってく気は改めてしました。
ExadataとPersistence Memory
以下の記事でも書いたのですが、Exadataについに不揮発性メモリが乗ってきました。
Intelの3D XPointが発表されてここまでくるのに長かったなぁ。まあ、今回はインメモリDBに使えるというよりは超高速なストレージとしての利用になりますが、こうした事例が増えてDBがアーキテクチャ的に進化したり、HPEのThe Machineのような近未来的なアーキテクチャが実際に出てくるようになると興味深いですよね。
これで量産化されて自宅マシンでも使えるようにならないかなー。まあ、Itaniumが自宅で使える価格/流通ではなかったので、期待しすぎると悲しくなるかもですが><
お得意のInfiniBandを捨てて100GbE + RoCE (RDMA over Converged Ethernet)を採用しています。40Gbpsという帯域から100Gbpsに上げつつ、RDMAをRoCEで処理することでレイテンシも確保しています。
「最速のコモディティサーバ」として設計されるExadataとしてパフォーマンスを上げつつフィットさせてきた感じですね。
今回のバージョンアップで帯域的/レイテンシー的なボトルネックにさらに改善ができたと思うので、やはり「僕の考えた最強のDBサーバ」としてのExadataは面白いですね。スペック厨的にワクワクするw
Oracle Cloudの戦略
さて、最後はOCIの話です。ここ最近Oraclegが力を入れてる気がするけどちょっとパッとしない、後発だからものは良さそうだけどなぁってポジションだったOCIですが今回は結構戦略を明確にしてきたと思います。
毎度のごとくAWSをディスりつつOracle DBをageてましたが、やはりOracleはデータベースの会社です。AzureにはWindowsやOffice365/ADとの親和性、GCPにはBigQueryとAIというキラーコンテンツがあるようにOCIのキラーコンテンツはDBだということを明確に出してきています。
なので、k8sやその他マネージドサービスなど他者との差分は追いつかせるけど、推しはやはりDB。単にRDBというだけじゃなくてAWSに比べて単一のアーキテクチャでDWHもトランザクションもグラフDBもドキュメントDBもやるよ、という点を強く出してました。
むしろ、Microsoftとの提携でイントラ系も基幹/業務系もエンプラ系は取り込みたいって感じですね。Web系に関してはスモールスタートができる料金体系になるかが鍵かなぁ。
特にShared環境Autonomous DatabaseはAWS Aurora Serverlessと同様に利用した分だけ課金するモデルのようなのでコストしだいですが最良のサーバレスRDBになり得るんじゃ無いかと。コストシミュレータで計算しようとするとバグってて常にゼロ円になる(そういうところだぞ、Oracle!)のですが、購入しようとすると最低1000ドルって書いてあるので多分そういう価格感ですね。ちょっと個人だと厳しそうかなぁ。
バックエンドが何しろExadataなので前述の通りのインフラスペックは言うに及ばずOracle Enterprise Editionをベースにしてるので暗号化やパラレルクエリやパーティションなどなど盛りだくさんでサポートしてるはず。この多機能性はMySQLやPostgreSQLベースでは実現できないところなので、どこまで使えるかは触ってみないとですが、私とても気になります!
そして、開発者フレンドリーなAlways Free!
検証目的という形ではありますが、個人でも企業でも2データベース、 1 CPU、 20 GBストレージが利用できます。無料で! とりあえず私も作ってみましたが、数分ポチポチすれば作れました。
今後、本格運用する前のシステムなら個人でも取りあえずOCIでAutonomous DBで作るってのはありかもしれないです。 当然、WordpressとかOracle DBに現状対応してないのですが今後そういうOSSも対応してくるかもですね。その布石なのか先日ついにOracle JDBCがMaven リポジトリに登録されました!
個人向けにはちょっぴり高そうな匂いがしますが、企業ユースだと十分良い選択肢かもですね。低スペックで良いので最低料金を下げるか、無料枠の規定に個人ユースも可とか明記してくれるとさらに最高ですがw
まとめ
キーノートがちょっとジェネリックすぎたり、ランチが微妙になってたりと少し肩透かし感もあったOCO2019ですが、発表できたしそれなりにたくさんの情報もキャッチできたと思うので良かったです。 来年も行けると良いな。
それでは、Happy Hacking!
カタログスペックで見るExadata X8M
Oracle OpenWorld 2019でExadata X8Mが登場しましたね! 基本的にExadataはOracleが毎年リリースする「僕の考えた最強のデータベース」です。 で、今回はついに夢の不揮発性メモリIntel Optena DCを本格搭載して登場しました!
不揮発性メモリってどのくらい速いんだろう? って気になったのでとりあえず過去にリリースされたExadataのカタログスペックと比較してみました。
https://docs.google.com/spreadsheets/d/1dC0wqfD-Dpe2VNObOqr2xs1dBnt15oVsMP8zU_06Pnw/edit?usp=sharing
まずはdatabase read I/O operations. なんと軽く2倍以上速いw
I/O letencyは過去機種のほぼ10倍ですね。
てか、この2つの値は少なくともX5から対して変わってないですね。そしてなぜかX6の数値が少し良い。 なので、システム全体の性能としてどのくらい影響があるかはちょっと謎だったりします。QPSと言うわけでも無いですし。 もしかしたら意外とかわらないかもですし、あるいは過去に類を見ないレベルで性能向上する可能性も無きにしも非ず。
この辺は門外漢なので教えて偉い人!
なんにしてもIntel Optena DCを本格利用ということで、これから生産体制が整って普通に買えるようになると嬉しいなぁ。
それではHappy Hacking!
参考: