猫でもわかるWebプログラミングと副業

本業エンジニアリングマネージャー。副業Webエンジニア。Web開発のヒントや、副業、日常生活のことを書きます。

Java の Web フレームワーク Quarkus を Google App Engine で使ってみる with Gradle

Quarkus について

Java のフレームワークといえは Spring が一番有名だと思います。

私は最近色々なフレームワークを触っていますが、Java の web フレームワークはどれも起動が遅いなと感じています*1

その中で、Quarkus が起動が早いという噂を聞いたので、試しに触ってみることにします。

構成

  • Java のバージョンは 21
  • ビルドツールは Gradle を使用
    • 一般的には Maven を使うパターンが多い気がしますが、今回は Gradle を使うことにします
  • Google App Engine で動かす
    • データベースは App Engine に標準装備されている Google Cloud Datastore を利用します

とりあえずローカルで動かすまで

基本的には Quarkus の Getting started の通りに進めます。

ja.quarkus.io

Quarkus コマンドのインストール

Quarkus には quarkus コマンド(CLI)があり、 quarkus コマンドでプロジェクトを作成したり、ローカルサーバーを起動できたりできます。

quarkus コマンドをインストールするには、JBang という Java のツールを使う方法と、SDKMAN というツールを使う方法があります。

今回は SDKMAN を使ってインストールしました。 SDKMAN は https://sdkman.io/ の通りにインストールし、SDKMAN をインストールすると sdk コマンドが利用できるようになるので、sdk コマンドで quarkus コマンドをインストールします。

sdk install quarkus

ちなみに、 Java のインストールにも SDKMAN が使えます。例: sdk install java 21.0.3-amzn

Quarkus プロジェクト作成

quarkus create コマンドを使って quarkus プロジェクトを作成できますが、いくつかオプションを指定できます。

まず、 quarkus create app で、アプリケーションのプロジェクト、 quarkus create cli で CLI のプロジェクトを作成できます。何も指定しなければ app になります。

--gradle オプションを指定すると gradle のプロジェクトになります。何も指定しない場合は maven になります。

--java=21 のように Java のバージョンを指定できます。

--name=XXXXX でプロジェクト名を指定できます。

--output-directory=XXXXX で、プロジェクトのディレクトリ名を指定できます。デフォルトだと code-with-quarkus というディレクトリが作成されす。

今回は以下のようなコマンドでプロジェクトを作成します。

quarkus create app --gradle --java=21

これで、 code-with-quarkus というディレクトリが作成され、その中に quarkus プロジェクトが作成されます。

Quarkus ローカルサーバー起動

その前に、生成されたコードを少し確認します。

生成された Quarkus プロジェクトを見てみると、デフォルトで GreetingResource.java というファイルが存在しており、/hello というエンドポイントが存在しています。

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

    Logger logger = Logger.getLogger(GreetingResource.class.getName());

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "Hello from Quarkus REST";
    }
}

Quarkus に限らず一般的な Java のフレームワークでは、@Path アノテーションがついたクラスまたはメソッドをもとに、リクエストをルーティングしてくれます。 @GET が GET リクエストに対応します。

@Produces は、レスポンスの Content-Type を表します。(逆に、 @Consumes はリクエストボディの Content-Type を表します)

では、ここから、quarkus のローカルサーバーを立ち上げて、実際にこの GET /hello にリクエストを飛ばしてみます。

以下のコマンドを実行すると quarkus のローカルサーバーが立ち上がります

quarkus dev

2024-04-21 16:37:46,737 INFO [io.quarkus] (Quarkus Main Thread) code-with-quarkus 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.9.4) started in 0.331s. Listening on: http://localhost:8080 のように表示されるので、 http://localhost:8080/hello にアクセスすると、 Hello from Quarkus REST と先程のレスポンスが表示されます。

Google App Engine に Quarkus をデプロイする

Google App Engine について

コードをデプロイするだけでいい感じに動かしてくれる Google Cloud のサービスです。 深い説明はここではしません。

Google App Engine の有効化

Google Cloud コンソールから App Engine (https://console.cloud.google.com/appengine) にアクセスすると、「App Engine へようこそ」の画面になるので、「アプリケーションを作成」をクリックします。

その後、リージョンとサービスアカウントの選択画面になります。

リージョンは一度選択すると変更できません。その Google Cloud プロジェクトの App Engine では、そのリージョンを使い続けることになります。

サービスアカウントは「App Engine デフォルトサービスアカウント」で良いと思います。

ここで「次へ」を押すと、そのプロジェクトで App Engine が使えるようになります。

App Engien の準備はここまでで OK です(以降は google cloud のコマンドで行います)

Google App Engine へのデプロイ

Google App Engine にデプロイするためには uber-jar という形式の jar ファイルを作成して、デプロイすればよいです。*2

src/main/resources/application.propertiesquarkus.package.type=uber-jar というプロパティを追加すれば、uber-jar 形式でビルドされるようになります。

quarkus.package.type=uber-jar

つづいて、App Engine 用のデプロイ設定 app.yaml を作成します。プロジェクトのルート(code-with-quarkus ディレクトリ直下)に作成します。app.yaml 無しでもデプロイはできるのですが、Java21 で動かしたい場合は app.yaml で指定する必要があります(デフォルトだと Java 17 になってしまうため)

今回は以下のように設定しました。

runtime: java21
instance_class: F2
automatic_scaling:
  max_instances: 1
  • instance_class: コードを動かすインスタンスのスペック。デフォルトで F2 になります。F1 だとインスタンスが小さすぎるので F2 にしています。
  • automatic_scaling.max_instances: オートスケールの設定が色々できるのですが、インスタンスが起動しすぎないように max_instances に1を指定しています。

プロジェクトルートに app.yaml を配置した状態で、 gcloud app deploy コマンドを実行します(gcloud は Google Cloud の CLI です。まだインストールしてない人はインストールしてください)。

gcloud が自動的に gradle を検出して、ビルド&デプロイしてくれるようです。

# 必ずログインした状態で deploy コマンドを叩く
$ gcloud auth login

# デプロイ
$ gcloud app deploy
Services to deploy:

descriptor:                  [/Users/XXXX/code-with-quarkus/app.yaml]
source:                      [/Users/XXXX/code-with-quarkus]
target project:              [xxxxxx]
target service:              [default]
target version:              [20240421t142108]
target url:                  [https://xxxxxx.uc.r.appspot.com]
target service account:      [App Engine default service account]


Do you want to continue (Y/n)?

Beginning deployment of service [default]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 36 files to Google Cloud Storage               ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...done.
Setting traffic split for service [default]...done.
Deployed service [default] to [https://xxxxx.uc.r.appspot.com]

デプロイが完了したら url にアクセスしてみてください。

cloud.google.com

Google Cloud コンソールの確認

Google Cloud コンソールで App Engine > バージョンを開くと、デプロイされている様子が確認できます。

「構成」をクリックすると、app.yaml で設定された内容などが表示されます。

「ログ」をクリックすると、Cloud Logging の画面が開き、ログを確認できます。アプリケーションが動いていない時はここからログを見ると良さそうです。

*1:体感ですが... JVM とかの関係もあるので、ある程度遅いのは仕方ないのかなとは思います

*2:uber-jar は uber eats とかとは関係ないです https://qiita.com/omix222/items/8d9a5411d6c1228ab3f1