BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース Micronaut 1.0への道 - JVMベースのフルスタックフレームワーク

Micronaut 1.0への道 - JVMベースのフルスタックフレームワーク

原文(投稿日:2018/10/19)へのリンク

1年の開発期間を経たMicronaut 1.0への道程は、この3週間、Object Computing(OCI)がリリース候補RC1RC2RC3を公開することで勢いを増している。以前はProject Particleという名で知られていたMicronautは、マイクロサービスベースのクラウドネイティブなサーバレスアプリケーションをJavaやGroovy、Kotlinで記述可能な、JVMベースのフルスタックフレームワークである。

Micronautは今年初め、プリンシパルソフトウェアエンジニアとしてOCIでGrailsやMicronautプロダクトのリーダを務めるGraeme Rocher氏によってGreach Conferenceで公開され、5月下旬にオープンソースとして公開された。

3つのリリース候補で導入された新機能は、GraalVMネイティブイメージのサポート、Swagger(OpenAPI)のコンパイル時サポート、コンパイル時バリデーション、コンパイル時のアノテーションのマッピングなどだ。RC3ではテスト用フレームワークのMicronaut Test 1.0 RC1もリリースされている。

Micronautは依存関係注入とAOT(Ahead-of-Time)コンパイルを使用する。Webサイトでの定義によると、

リフレクションベースのIoCフレームワークでは、コード内のすべてのフィールド、メソッド、およびコンストラクタのリフレクションデータがロードされ、キャッシュされます。これに対してMicronautでは、アプリケーションの起動時間とメモリ消費量はコードベースサイズの影響を受けません。

Netty上に構築されているMicronautは、独自の非ブロッキングWebサーバをバンドルして提供される。メモリ消費量を削減するように設計されたMicrronautリアクティブクライアントは、宣言的な構築が可能で、コンパイル時に実装される。

プロファイル

Micronautはいくつかのプロファイルが組み込まれており、スケルトンや、現在まだ開発中ではあるが、Webあるいはコマンドラインアプリケーションのビルディングブロックとなるアプリケーションを生成することが可能である。個々のプロファイルはテンプレートと、プロファイル固有の追加コマンドで構成されている。例えばcreate-appはサービスプロファイルを開始するためのもので、コントローラ(create-controller)およびクライアント(create-client)クラスを構築するためのコマンドが含まれている。これらのコマンドは、他のプロファイルでは使用できない。

始めに

Micronautのダウンロードとインストールを行った上で、コマンドラインあるいはMicronautシェルでアプリケーションを生成する。Grailsの慣れ親しんだコマンドラインインターフェースを参考に、Micronautでは、アプリケーション生成に同じコンセプトを用いている。次のコマンドを考えてみよう。

    
$ mn create-app org.redlich.demo
    

以下に示すように、このコマンドは、demoというルートフォルダ下にJavaアプリケーションとGradleプロジェクトを生成し、パッケージ名をorg.redlichにする。

テストディレクトリ構造、Dockerfile、YAMLコンフィギュレーションファイルが含まれていることに注目してほしい。micronaut-cli.ymlファイルは、プロジェクトに関する独自の情報を提供するものだ。

    
profile: service
defaultPackage: org.redlich
---
testFramework: junit
sourceLanguage: java
    

生成されたJavaソースファイルApplication.javaがMicronautサーバを起動する。

    
package org.redlich;

import io.micronaut.runtime.Micronaut;

public class Application {

    public static void main(String[] args) {
        Micronaut.run(Application.class);
        }
    }
    

この初期アプリケーションは、次のようにビルドおよび実行する。

    
$ ./gradlew run
    

上のプロジェクトにコントローラを追加するには、次のコマンドを実行する。

    
$ mn create-controller HelloController
    

以下に示すように、HelloController.javaHelloControllerTest.javaというファイルがプロジェクトに追加される。

生成されたHelloController.javaファイルでは、@Controllerアノテーションのエンドポイントが、コントローラの名称であるHelloControllerに基づいて、“/hello”という名前になっている点に注目してほしい。

    
package org.redlich;

import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.HttpStatus;

@Controller("/hello")
public class HelloController {

    @Get("/")
    public HttpStatus index() {
        return HttpStatus.OK;
        }
    }
    

JavaとGradleがそれぞれ、デフォルトの開発言語とビルドツールである。GroovyとKotlinのアプリケーションは、次のようにして生成する。

    
$ mn create-app org.redlich.demo --lang groovy
$ mn create-app org.redlich.demo --lang kotlin
    

Mavenプロジェクトの生成もサポートされている。

    
$ mn create-app org.redlich.service --build maven
$ ./mvnw compile exec:exec
    

こちらのMicronautチュートリアルの第1部では、Java、Groovy、Kotlinの3つの言語で3つのマイクロサービスを作成する方法について、OCIのソフトウェアエンジニアであるSergio del Amo Caballero氏が解説している。

Rocher氏がInfoQに、最新リリースについて話してくれた。

InfoQ: OCIがこのマイクロサービスフレームワークを新たに開発した理由は何だったのでしょう?

Graeme Rocher: この数年の間にテクノロジの状況は大きく変わりました。特にDockerやKubernetesといったシステムやサーバレスの動向を見ると、メモリ使用量の少ないマイクロサービスや、再起動時のオーバヘッドが低いアプリケーションに最適化されていることが分かります。その結果として、コールドスタート時のパフォーマンスやメモリ消費量の面で優れたGoやNodeといった言語が、大きな弾みをつけています。ここで考えるべきなのは、DockerやKubernetesの開発チームにテクノロジの選択権が委ねられている今、それらのプラットフォームではなぜJavaよりもGoが選ばれているのか、ということです。私の考える答は簡単です - 今日利用可能なテクノロジの中から、彼らがもしJavaを選択してそれらのテクノロジをJavaで記述していたとすれば、ローカル実行のためには開発者すべてがスーパーコンピュータを所有しなければならなくなるからです。

この理由はさまざまですが、その一方では、言語レベルの制限というものも存在します。JVMは素晴らしい技術的成果ですが、サーバレス関数のような短命のオペレーションでは、JVMの持つ最適化の効果が失われることが多い上に、アプリケーションを実行するためのJVM全体を持ち込まなければならないという問題もあります。GraalVMのようなプロジェクトがJavaアプリケーションをネイティブイメージにコンパイル可能にすることで、これらの制限が解決される可能性もありますが、Javaアプリケーションをより効率的にするためには、率直に言ってフレームワークデザイナが大きな役割を果たします。

フレームワークレベルでは、従来のJVMフレームワーク(SpringやJava/Jakarta EEなど)はモノリシックアプリケーションが主流であった10年以上前のもので、リフレクションや実行時のアノテーション解析などを中心として構築されています。このアプローチが問題なのは、型消去(type erasure)から制限付き注釈API、リフレクションロジックの動作速度上の問題に至るまでのさまざまな問題によって、高速起動と低メモリ消費を両立するJavaフレームワークの構築がほぼ不可能であることです。そのため、フレームワークのランタイムにかかる負担は膨大なものになります。Springが実行時に何をしているかを見れば、バイトコードをASMで字句解析してアノテーションメタデータを生成することから、リフレクション情報を積極的にキャッシュすることで繰り返し読み込みに起因する速度低下を回避していることまで、大いに驚くことでしょう。このランタイム情報のすべてをキャッシュすることの必要性と、高速起動と低メモリ消費を達成するという目標との間には、相容れない矛盾が存在しています。

リフレクションの使用を制限し、アノテーションメタデータやプロキシ、フレームワークインフラストラクチャなどを一連のアノテーションプロセッサによってコンパイル時に解決し、AOT(Ahead-of-Time)コンパイルを実行するAST変換を備えることでこの矛盾を解決したMicronautは、将来のフレームワークの基盤だと思っています。これにより、スタートアップの高速化と低メモリ消費量が実現可能になったと同時に、GraalVMネイティブイメージとの互換性も大きく改善されています。

もちろん、Javaのエコシステムは、SpringやKafka、Cassandra、Hadoop、GrailsなどJavaベースの膨大なプロジェクトと、GroovyやScala、Kotlin、Java、Clojureなどリッチな言語エコシステムを備えた巨大なものですから、メモリ使用量の少ないマイクロサービスやサーバレスがすべてではありませんし、JVMやJITから多大なメリットを受けられるワークロードもたくさんあります。ですが、そのようなワークロードであったとしても、単純にスタートアップとメモリ使用量の両面において他のフレームワークより効率的であるという理由から、Micronauで得られるものは多いと考えています。

InfoQ: MicronautのサポートするJVMベース言語として、ScalaやClojureを含める予定はありますか?

Rocher: Micronautは元々、複数の言語を念頭に開発されているのですが、現時点ではJava、Kotlin、Groovyを、各言語用の共通ASTを開発することでサポート対象としています。将来的には、Scalaコンパイラプラグインを使ってScalaをサポートする計画です(https://github.com/micronaut-projects/micronaut-core/issues/675参照)が、作業を進める上で協力をしてくれるScalaコミュニティのメンバがいれば、ぜひ連絡を頂きたいと思います。Clojureには興味を持っていますが、どうやって実現すればよいのか、Clojureコミュニティから何らかのインプットが必要です。

InfoQ: GraalVMはJVMベース以外の言語もサポートしていますが、そのような言語をMicronautアプリケーションの開発に使用することは将来的に可能でしょうか?

Rocher: サイドカーを使用すれば、他の言語をMicronautアプリケーションに統合することは難しくないと思っています。

InfoQ: MicronautのGAリリースはいつの予定ですか?

Rocher: Micronaut 1.0 GAが10月23日にリリースされる予定です。

InfoQ: Micronautの計画について教えてください。GAリリース後はどのような予定がありますか?

Rocher: Micronaut 1.0では、基盤となる安定したベースラインを確立します。MicronautはAOTコンパイラを使用するので、1.0リリースではコンパイル前のメタデータ形式を安定化する必要があります。1.0をリリースしたら、RabbitMQやKubernetes、GRPC、GraphQLなど、より多くのテクノロジと統合を図りたいと思っています。

リソース

 
 

この記事を評価

採用ステージ
スタイル
 

この記事に星をつける

おすすめ度
スタイル

BT