こんにちは。
キャスレーコンサルティングのIT部の内田です。

今回は、JavaのWebアプリケーションフレームワーク「Quarkus」をご紹介します。

■Quarkusとは

2019年3月に、Red Hatより発表されたJava Webアプリケーションフレームワークです。

https://quarkus.io/

Publickey寺田佳央さんのブログでも紹介されているなど、
業界内で大変注目を集めている技術です。

■何がいいのか

Publickeyによれば、Quarkusの特徴は具体的に2つあるとあります。

〜以下引用〜

1つはプログラミングにおけるフレームワークとしてのQuarkusで、プログラミングにおいてインペラティブ(Imperative)なモデル、すなわち実行すべき命令を1つ1つ順番に記述していく比較的伝統的といえるモデルと、リアクティブ(Reactive)なモデル、すなわち(説明するのが難しいのですが)扱っている値の変更や関係性を中心に記述する最近注目されているモデルの両方を可能にするというもの。

そしてQuarkusのもう1つの特徴が、Javaアプリケーションのコードからネイティブバイナリを作成し、コンテナ化することで瞬時にJavaアプリケーションが起動し、メモリ消費量も少ない、コンテナやKubernetes環境に最適化された実行形式を実現できることです。

〜引用ここまで〜

特に2つ目の点、システムの起動が非常に早くなる点について、
GraalVM上で動作させる事によりGraalVMのネイティブコンパイル機能を使う事で、
起動時間を劇的に短縮させる事ができるとの事です。

Quarkus発表後の大きなトピックとして、GraalVMの商用版(19.0)リリースがありました。
https://www.publickey1.jp/blog/19/graalvmgraalvm_190javajavascriptgraalvm_enterprise_edition.html

これにより、GraalVM+Quarkusの構成が本番利用可能な技術として大きく前進したといえるでしょう。

■今回やってみたこと

今回は、Quarkusの公式チュートリアルを一通りやってみました。
 ・Quarkusアプリケーションの作成
 ・GraalVMを使用したネイティブコンパイル
 ・dockerイメージの作成
 ・Kubernetesへのアプリケーションデプロイ

検証環境
 macOS Mojave(10.1.3)
 Docker for Mac 18.09.2
 Maven(3.5.3) ※Mavenは3.5.x以上でないと動作しないようです。
 jenv導入済

■事前準備

1. GraalVMのインストール
 https://www.graalvm.org/

GraalVMは、上述のとおり商用版の提供がスタートしており、
Oracle公式サイトよりEnterprise Editionをダウンロードしました。
 https://www.oracle.com/technetwork/graalvm/downloads/index.html

ソースコードからコンパイルしても良いようですが、今回は割愛しました。

2. Docker
brewからDockerをインストールしておきます。
Dockerイメージは、チュートリアル内で取得するため事前準備は不要です。

■ Quarkusのmavenプロジェクトをチェックアウト

https://quarkus.io/guides/getting-started-guide

Quarkusのチュートリアルに沿って、mavenプロジェクトを作成します。

以下のmavenコマンドを実行すると、サンプルプロジェクトがローカルにチェックアウトされます。

$ mvn io.quarkus:quarkus-maven-plugin:0.15.0:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=getting-started \
    -DclassName="org.acme.quickstart.GreetingResource" \
    -Dpath="/hello"
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- quarkus-maven-plugin:0.15.0:create (default-cli) @ standalone-pom ---

 (〜中略〜)

[INFO]
[INFO] Maven Wrapper version 0.5.5 has been successfully set up for your project.
[INFO] Using Apache Maven: 3.6.1
[INFO] Repo URL in properties file: https://repo.maven.apache.org/maven2
[INFO]
[INFO]
[INFO] ========================================================================================
[INFO] Your new application has been created in /Users/sabu/dev/git/casley/quarkus/tutorial/.
[INFO] Navigate into this directory and launch your application with mvn compile quarkus:dev
[INFO] Your application will be accessible on http://localhost:8080
[INFO] ========================================================================================
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.725 s
[INFO] Finished at: 2019-06-02T07:51:12+09:00

■動かしてみる

プロジェクトフォルダ直下で以下のコマンド実行すると、サンプルが実行できます。

$ ./mvnw compile quarkus:dev
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< org.acme:getting-started >----------------------
[INFO] Building getting-started 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ getting-started ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ getting-started ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/sabu/dev/git/casley/quarkus/tutorial/target/classes
[INFO]
[INFO] --- quarkus-maven-plugin:0.15.0:dev (default-cli) @ getting-started ---
 (〜中略〜)
Listening for transport dt_socket at address: 5005
2019-06-02 08:00:55,791 INFO  [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus augmentation
2019-06-02 08:00:56,517 INFO  [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed in 726ms
2019-06-02 08:00:56,858 INFO  [io.quarkus] (main) Quarkus 0.15.0 started in 1.158s. Listening on: http://[::]:8080
2019-06-02 08:00:56,860 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy]

動いています。

■プロジェクトをIDEで開いてみる

Eclipseでプロジェクトを開いてみます。
EclipseのJRE設定は、GraalVMにしておきました。

■プログラムの修正

チュートリアルに沿って、少しプログラムを修正します。


GreetingResource.java
package org.acme.quickstart;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class GreetingResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello!!";
    }

    @GET
    @Path("/{inputString}")
    @Produces(MediaType.TEXT_PLAIN)
    public String helloSomeone(@PathParam("inputString") String inputString) {
        return "hello " + inputString + " san!!";
    }

}

テストコードも修正します。


GreetingResourceTest.java
package org.acme.quickstart;

import static io.restassured.RestAssured.*;
import static org.hamcrest.CoreMatchers.*;

import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
public class GreetingResourceTest {

    @Test
    public void testHelloEndpoint() {
        given()
          .when().get("/hello")
          .then()
             .statusCode(200)
             .body(is("hello!!"));
    }

    @Test
    public void testHelloSomeone() {
        given()
          .when().get("/hello/casley")
          .then()
             .statusCode(200)
             .body(is("hello casley san!!"));
    }
}

■ネイティブイメージの作成

GRAALVM_HOMEの設定
ネイティブイメージ作成時点で必要になります。

$ export GRAALVM_HOME={GraalVMのインストールディレクトリ}/Contents/Home/
$ source ~/.bash_profile
./mvnw verify -Pnative

ネイティブビルドが、可能かどうか検証します。
実際開発する場合、ここまでで1サイクルかと思います。

[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< org.acme:getting-started >----------------------
[INFO] Building getting-started 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
〜中略〜
[INFO]
[INFO] --- maven-failsafe-plugin:2.22.0:verify (default) @ getting-started ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  01:34 min
[INFO] Finished at: 2019-06-07T20:37:26+09:00
[INFO] ------------------------------------------------------------------------
./mvnw package -Pnative -Dnative-image.docker-build=true

Docker向けのネイティブイメージを作成します。

実行

$ docker run -it --rm -p 8080:8080 quarkus-quickstart/quickstart:latest
2019-06-02 23:03:34,972 INFO  [io.quarkus] (main) Quarkus 0.15.0 started in 0.006s. Listening on: http://0.0.0.0:8080
2019-06-02 23:03:34,972 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy]

ネイティブイメージを実行しているため、起動速度が非常に早いのが分かります。

先ほどの『動かしてみる』の際は、システム起動に1.158秒かかっていたのに対し、
今回は0.006秒で起動しています。

■Kubernetesのインストール、Minikubeの設定

Kubernetesネットワーク向けに、Quarkusアプリケーション公開の設定を行ないます。

私の場合、今までKubernetesを使った事がなかったので、
Kubernetes(kubectl,Minikube)のセットアップを行ないました。

 https://kubernetes.io/docs/tasks/tools/install-kubectl/
 https://kubernetes.io/ja/docs/setup/minikube/

■kubectl, Minikubeとは

ここでは詳細は割愛しますが、それぞれざっくりご説明すると

〜以下引用〜

kubectlは、Kubernetesクラスターの管理用コマンドラインツールです。 Minikubeはローカル環境でKubernetesを簡単に実行するためのツールです。Kubernetesを試したり日々の開発への使用を検討するユーザー向けに、PC上のVM内でシングルノードのKubernetesクラスタを実行することができます。

〜引用ここまで〜

公式ガイドが非常に充実しており、特に詰まる事なく完了しました。
Minikubeのインストール時、途中でVirtualBoxのインストールを求められたりなどしました。
VirtualBox以外の各種仮装技術にも対応しているようです。

DockerイメージをKubernetesクラスターに登録

$eval $(minikube docker-env)

Dockerイメージを生成します。

$ docker build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/quickstart .

生成したDockerイメージをKubernetesクラスター上にデプロイします。

$ kubectl run quarkus-quickstart --image=quarkus-quickstart/quickstart:latest --port=8080 --image-pull-policy=IfNotPresent
$ kubectl expose deployment quarkus-quickstart --type=NodePort
http://192.168.99.100:31328/

Kubernetesクラスター上でQuarkusアプリケーションが起動しています。 うまくいきました。

■まとめ

いかがでしたでしょうか。

今回はQuarkusのご紹介と、Quarkusの各種チュートリアルについてハンズオンしてみました。
正直なところ、Docker/Kubernetesといった技術群にはまだまだ個人的に分からない事が多く、
「ただ動きました」感がある点は否めないですが、私自身Quarkusに触れてみることで、
今までほとんど触れる事のなかったモダンなwebアプリ環境を
実際に動かしてみる機会を作ることができました。

今後、採用が増えそうな技術でもあり、皆様も試してみてはいかがでしょうか?

最後までお読みくださり、ありがとうございました。

参考資料

Publickey
 https://www.publickey1.jp/
寺田佳央さんのブログ
 https://yoshio3.com/
Quarkus 公式サイト
 https://quarkus.io/
Kubernetes 公式サイト
 https://kubernetes.io/

他、各種Web上で公開された技術資料群を参考にさせて頂きました。
各種技術情報や調査結果の公開に、心より感謝いたします。

内田佐武郎
CSVIT事業部 内田佐武郎
今回はJava界隈の新しめのトピックを何か書きたいと思い、Quarkusをご紹介させて頂くこととしました。