前編だけでは終われない理由
前編の記事では、JavaのWebフレームワークのうちリクエスト処理について紹介しました。
▼前編はこちらをチェック
2010年ごろであればそれでフレームワークの紹介を終わりとしてもよさそうなのですが、現在ではリクエスト処理の書き方だけではなく、どのようにデプロイしてどのように動くかというのも大事になって、フレームワークというとそこまで含めたフルスタックで考える必要があります。
そこで今回はフルスタックフレームワークがどのように必要になったのかという流れを説明し、Java EEなどJava標準がどのように変わってきているかなど、フレームワークのとりまく状況を整理していきます。
Webフレームワークの役割の変化
Webフレームワークの役割をまとめてみると、次のようになります。
- HTTP処理
- HTTPリクエストの解析
- ルーティング
- 出力
- Webアプリケーション処理
- セッション管理
- 認証/認可
- リソース管理
- サーバー管理
- 実行管理
- 設定管理
- モニタリング
- パッケージング
- 実行バイナリの作成
初期には、Java EEが全体をカバーし、HTTP処理とWebアプリケーション処理に関してはサーブレットが行い、サーバー管理に関してはTomcatやJBossなどが独自に設定の管理やモニタリングなどを行っていました。フレームワークはサーブレット上でのHTTP処理を行いやすくするという位置づけです。
パッケージングに関しては、WARファイルかJARファイルでアプリケーションサーバーにデプロイするという一択でしたが、クラウドやマイクロサービスなどの普及で変わってきています。
そのため、これらをすべて管理するフルスタックフレームワークが主流になっています。
この図の中で、Spring Boot、Quarkus、Micronautは製品名ですが、Jakarta EEとMicroProfileは規格で、その規格にあわせた対応製品がいろいろ出ています。
QuarkusもMicroProfileに準拠していますが、独自性が強いため、製品として紹介しています。
デプロイ方法の変化
フレームワークの変化で大きいのは、デプロイ方法にサーブレットコンテナへのデプロイ以外に次のような選択肢ができたことです。
- 埋め込みサーバー
- Dockerなどのコンテナ
- ネイティブバイナリ
このような変化の背景を説明していきます。
■サーブレットコンテナへのデプロイ
JavaのWebフレームワークは、2000年のStrutsに始まり、元々はサーブレット上でのアプリケーションを書きやすくする仕組みでした。サーブレットは、サーブレットコンテナというアプリケーションサーバーにデプロイするという前提になっています。サーブレットコンテナへは、複数のWebアプリケーションをデプロイすることが可能でした。
2000年ごろはサーバーが高価で、アプリケーションサーバー自体のメモリ使用量も相対的に多かったため、できるだけ共通化して節約し、複数のアプリケーションを動かせるようにするという目的があったと思われます。
ただ、開発時ではTomcatなどのサーブレットコンテナを手元にあらかじめインストールし、試しに動かすときにデプロイする必要があるなど、手間が多くなっていました。
■埋め込みサーバー
2010年あたりを境に、クラウドが流行しはじめました。この背景には、CPUがマルチコア化しメモリも安くなるなどしてハードウェアの性能があがったという供給側の条件と、スマホと4GでのWebの高機能化、常時接続化によるトラフィック増大という需要側の条件がリンクしたことがあると考えられます。
アプリケーションサーバーを動かすための数メガバイト程度のメモリはすでに誤差になっており、サーブレットコンテナとして複数のWebアプリケーションを動かす需要はなくなっていました。逆に、スケールアウトとして、同じアプリケーションを多数のサーバーで動かす需要が増えていました。そうすると、アプリケーションサーバーのインストールやデプロイといった作業は、メリットのないただの手間になります。アプリケーションをビルドしてそのバイナリだけで実行できるほうが効率的です。
2014年にリリースされたSpring BootではTomcatをライブラリとして組み込み、アプリケーションを起動するだけでサーバーが動いてデプロイが行われ、余計な手間が不要になりました。このような埋め込みサーバーは、現在のフレームワークでは標準になってきています。
■マイクロサービスとDocker、Kubernetes
クラウドサービスは仮想的なコンピュータを使っていました。そういった仮想コンピュータはハードウェアのエミュレーションを含みOSをまるごとインストールしていましたが、複数のサーバーを動かしたいだけであれば独立したLinuxのように見えればいいだけなので、ハードウェア全体のエミューレーションは過剰になります。そこで、OSのカーネルまでを共有化して、プロセスIDやディスクマウント、ポート番号などOSリソースだけを独立させたDockerが2013年にリリースされ、コンテナと呼ばれます。コンテナは、OSリソースが隔離された特別なプロセスなので、起動も素早いです。
2014年には、マイクロサービスというアーキテクチャがジェームス・ルイス氏とマーチン・ファウラー氏により提唱されました。ひとつの大きなサービスとして実装されていたWebアプリケーションを、小さなマイクロサービスにわけて開発するという考え方です。マイクロサービスの運用面でのメリットとして効率的なサーバー利用があげられます。アクセス頻度の違う機能を別のサービスにわけることで、アクセスの多い機能には多数のサーバーを割り当て、アクセスが少ない機能には少数のサーバーを割り当てることで、サーバーのムダがなくなります。
そこでサービスの状況にあわせてサーバーを増やしたり減らしたりということが頻繁に行われるようになると、仮想マシンの起動時間にまぎれて誤魔化すことができていたSpring Bootの起動時間が問題になってきます。Spring Bootではアノテーションの解決を実行時に行うため、システムが大きくなるほど起動に時間がかかるようになります。
そこでアノテーションの解決をコンパイル時に行うなどして起動時間を短縮したのがQuarkusとMicronautです。サーバーにはNettyというフレームワークを採用して軽量化をはかっています。Nettyはサーブレットコンテナではないため、QuarkusやMicronautはサーブレットに依存していません。
また、多数のサーバーが連携することが前提になると、サーバーへの通信ができないことにも対応する必要があります。そこでリトライやヘルスチェックといった耐障害性に関する機能や、サーバーをまたがった呼び出しのトレースなど監視を仕様に含んだMicroProfileも始まりました。QuarkusはMicroProfileに準拠しています。
■サーバレスとネイティブ化
マイクロサービスによって、アクセスが多い機能に多数のサーバーを割り当て、アクセスされない機能には少数のサーバーということを進めていくと、サーバー1台分を割り当てるまでもないような機能も出てきます。そこで、機能のために特別にサーバーを用意せず、アクセスがあったときにプロセスを立ち上げ、アクセスへの応答を行えばプロセスを終了するという、サーバレスという考え方が広まります。
そういったサーバレス環境でJavaを使おうとすると、JVM自体の起動時間も気になってきます。JavaではJVMの起動に加えて、実行時最適化を行っているため、一度だけの実行には無駄が多いことになります。
そこでJavaコードをネイティブコードにコンパイルして実行できるGraalVMのNativeImageが注目されるようになっています。また、Java標準でもProject Leydenという起動を速めるためのプロジェクトが立ち上がっています。
■開発者モード
デプロイの流れとは少し違いますが、Javaでの開発ではソースコードを書き換えるとビルドしたあとにサーバー再起動が必要になり、試行錯誤しながらの調整は面倒になります。
そのため、サーバーを動かしたまま変更を反映させることができる開発者モードを持ったフレームワークもあります。
Quarkusの開発者モードでは、サーバーの実行状況の確認もできて便利です。コードを変更することなく開発時の機能が使えるので、開発用画面をうっかり本番で公開してしまい個人情報漏えいなどの問題になるということも防げます。
Java標準
最後にJava標準についてまとめておきます。
10年前であれば、このようなWebフレームワークに関する記事では真っ先にJava EEの話題になり、Java EEにどのような機能が入るかということが注目を集めました。しかし今では、Java EE / Jakarta EEの最新情報を気にする人はあまりいないように思います。
そのため最後にとりあげることにしたのですが、なぜそのように影が薄くなったのかもとりあげます。
■Java EEからJakarta EEへ
JavaのWebアプリケーション標準はJava EEとしてまとめられていました。Java EE 7が2013年にリリースされましたが、先ほども挙げたように、この時期はアクセス数の急増やクラウド対応など周辺の環境に大きな変化がある中で、その変化に対応しているとは言い難いものでした。そして、その次のバージョンであるJava EE 8はなかなか作業が進んでいません。
そういった中で、Java EEを進めないオラクルへの不満から2016年に「Java EEガーディアンズ」が立ち上がりました。
その結果2017年9月にJava EE 8のリリースと共に、Java EEはEclipse財団に移管されることになりました。オラクルのもとを離れることで、「Java」の名前が使えなくなったため、Java EE 8と同じ内容のものが2019年9月にJakarta EE 8としてリリースされ、「javax」というパッケージ名も使えなくなったため、2020年12月にパッケージ名のみを「jakarta」に変更したバージョンがJakarta EE 9としてリリースされます。たとえばjavax.servlet.http.HttpServlet
はjakarta.servlet.http.HttpServlet
に変更になっています。
そして2022年12月に機能更新をしたJakarta EE 10がリリースされています。しかし、Java EE 8でもあまり大きな変化がなかったことを考えると、Java EE 7から9年たってのバージョンアップとも言えるため、その間に影が薄くなったのも無理はないと言えます。
また、Java EEの減速には、Java EEが実現しようとしていた高度なサーバー管理機能が、Kubernatesなどコンテナをベースにした技術で代替されていったというのもあります。たとえばメモリやプロセッサの利用状況の監視や複数台のサーバーでのクラスタリングなどの機能は、コンテナで実現するほうが他のサーバーとも統一的に扱えて便利です。
そのため、Java以外も含めた現在のWebフレームワークでは、クラスタリングなどの機能はコンテナ管理システムにまかせて、Webの処理に特化する方向になっています。
■Jakarta EE 10
Jakarta EE 10は次のサイトでまとめられています。
内容としては次の図のように、3つのプロファイルにわかれています。Webプロファイルやプラットフォームは以前のバージョンからありましたが、Jakarta EE 10からは最低限の機能をまとめたコアプロファイルが導入されています。
コアプロファイルにサーブレットが含まれていないことも時代を反映していると思います。
Jakarta EEを始めるためのスターターが用意されたのも時代に追随しているといえます。
Jakarta EEに対応した実行環境が選べるようになっていますが、いずれもプロジェクトを起動すればサーバーが起動して自動的にデプロイが行われるようになっています。
このフォームはJSFでPrimeFacesを使って作られているようです。また、Runtimeの並び順はランダムです。特定の優先順位付けを行わないように気が払われていますね。
■MicroProfile
2013年にJava EE 7がリリースされたあと2017年にJava EE 8がリリースされたとはいえ、2022年のJakarta EE 10まで大きな変更がなかったのですが、その間に新たな仕様が出てこなかったわけではありません。
Java EEが進まない中、ほぼJava EEガーディアンズと同じメンバーが立ち上げたのがMicroProfileです。
この「Micro」は、プロファイルとして小さいことを意味するのではなく、マイクロサービスに対応したプロファイルであることを表します。そのため、Jakarta EEコアプロファイルにメトリクスやトレーシングといった監視用機能と、ヘルスチェックやリトライのような耐障害性に対応する機能を加えたものになっています。
フレームワークの流れがWebの処理に特化する方向になっていると書きましたが、コアプロファイルやMicroProfileはJavaでその流れを具体化したものということもできます。
MicroProfileもスターターが用意されていて、気軽に試すことができるようになっています。
このサイトもJSFとPrimeFacesで作られていますね。
MicroProfileはサーブレットを含まないJakarta EEコアプロファイルを中心にしているため、埋め込みサーバーが基本です。
MicroProfileで標準化している監視や耐障害性の機能はJakarta EEでも必要なはずです。MicroPfofileとJakarta EEでのランタイムには共通したものが多く、参加メンバーも重複していると思われるので、統合されたほうがわかりやすい気がしますね。
Webフレームワークの状況のまとめ
Java EEの失速もあって、現在ではSpring Bootがかなりのシェアを占めており、とくにこだわりがなければSpring Bootを使うのが無難という状況です。
ただ、起動時間などの問題に対応するためにQuarkusやMicronautがあらわれ、特にQuarkusはJava EEからの移行がやりやすいこともあって、シェアを伸ばしています。
Micronautは独自のAPIで基本的な処理をまかなっています。そこで、そのAPIが使いやすいと感じた場合にはMicronautが採用されるようです。
小さいWebサービスではJavalinが便利でしたが、Helidon SEも有力な候補になりそうです。ただ、そういった用途に向けたHelidon SEのドキュメントは不親切で、結局Javalinが使いやすいかもしれません。
Jakarta EEやMicroProfileでは、Quarkusが独自性もあって注目されていますが、他の実行環境は存在感が出せていないように思います。標準自体の注目度が下がっている現状では、標準に準拠しているだけでは価値を認められにくいということでしょう。
さいごに
JavaのWebフレームワークを選ぶ際には、フレームワークの機能の特徴だけではなく、現在のWeb開発の状況も踏まえておく必要があります。
この記事が、そういった状況の把握の助けになれば幸いです。
九州芸術工科大学芸術工学部音響設計学科を8年で退学後、フリーランスでの活動を経て、2015年から大手IT企業勤務。著書に、『プロになるJava 』(共著、技術評論社)、『みんなのJava OpenJDKから始まる大変革期!』(共著、技術評論社)、『創るJava』(マイナビ)など。
※本記事に記載されている会社名、製品名はそれぞれ各社の商標および登録商標です。