Google Cloud Functions (Serverless)
previewquarkus-google-cloud-functions エクステンションを使用すると、Quarkusを使用してGoogle Cloud Functionsを構築することができます。関数では、CDIやSpringからのインジェクションアノテーションや、必要に応じて他のQuarkusの機能を使用できます。
|
この技術は、previewと考えられています。 preview では、下位互換性やエコシステムでの存在は保証されていません。具体的な改善には設定や API の変更が必要になるかもしれませんが、 stable になるための計画は現在進行中です。フィードバックは メーリングリスト や GitHub の課題管理 で受け付けています。 とりうるステータスの完全なリストについては、 FAQの項目 を参照してください。 |
前提条件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 11+ がインストールされ、
JAVA_HOMEが適切に設定されていること -
Apache Maven 3.8.6
-
使用したい場合は、 Quarkus CLI
-
Google Cloudのアカウント 。無料アカウントが使えます。
ソリューション
このガイドでは、サンプルプロジェクトを生成し、Quarkusで HttpFunction 、 BackgroundFunction 、 RawBackgroundFunction を実装する方法を説明します。ビルド後は、プロジェクトをGoogle Cloudにデプロイすることができます。
これらの手順を順にすべて実行しない場合、完成したサンプルを以下で確認できます。
git clone https://github.com/quarkusio/quarkus-quickstarts.git で Git リポジトリーをクローンします。または、https://github.com/quarkusio/quarkus-quickstarts/archive/main.zip[アーカイブ] をダウンロードします。
このガイドでのソリューションは google-cloud-functions-quickstart directory にあります。
Maven デプロイメントプロジェクトの作成
quarkus-google-cloud-functions のエクステンションを持つアプリケーションを作成します。以下のMavenコマンドを使って作成します。
関数の作成
このプロジェクトの例では、 HttpFunction 、 BackgroundFunction (ストレージイベント)、 RawBackgroundFunction (PubSubイベント)、 CloudEventsFunction (Cloud Events 仕様を使用したストレージイベント)の4つの関数を作成します。
Quarkus supports Cloud Functions gen 1 and gen 2. For an overview of Cloud Functions gen 2 see this page on the Google Cloud Functions documentation. To use gen 2 you must add the --gen2 parameter.
|
Cloud Functions の関数を選択する
quarkus-google-cloud-functions エクステンションは、プロジェクト内からGoogle Cloud HttpFunction 、 BackgroundFunction 、または RawBackgroundFunction 、 CloudEventsFunction インターフェイスを直接実装しているクラスをプロジェクト内でスキャンします。プロジェクト内でこれらのインターフェイスを実装しているクラスが見つからなければ、ビルド時にエラーがスローされます。 複数の関数クラスが見つかった場合は、ビルド時の例外がスローされます。
しかし、同じコードを利用するCloud Functionの関数クラスが複数あるような場合に、個別maven モジュールを作成することは手間となります。このQuarkusエクステンションを使うと、複数のCloud Function関数を一つのプロジェクトにバンドルし、設定や環境変数を使ってデプロイしたい関数を選択することができます。
Cloud Functions の関数に名前を設定するには、以下の設定プロパティーを使用します。
quarkus.google-cloud-functions.function=test
quarkus.google-cloud-functions.function プロパティーは、デプロイする関数をQuarkusに伝えます。これは環境変数でオーバーライドすることもできます。
Cloud Functions の関数となるクラスの CDI 名は、 quarkus.google-cloud-functions.function プロパティー内で指定された値と一致している必要があります。これは @Named アノテーションを使用して行う必要があります。
@Named("test")
public class TestHttpFunction implements HttpFunction {
}
HttpFunction
import java.io.Writer;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import io.quarkus.gcp.function.test.service.GreetingService;
@Named("httpFunction") (1)
@ApplicationScoped (2)
public class HttpFunctionTest implements HttpFunction { (3)
@Inject GreetingService greetingService; (4)
@Override
public void service(HttpRequest httpRequest, HttpResponse httpResponse) throws Exception { (5)
Writer writer = httpResponse.getWriter();
writer.write(greetingService.hello());
}
}
| 1 | @Named アノテーションでは、 quarkus.google-cloud-functions.function プロパティーで使用する CDI Beanに名前を付けることができますが、これはオプションです。 |
| 2 | 関数はCDI Beanでなければなりません。 |
| 3 | これは通常の Google Cloud Function の実装なので、 com.google.cloud.functions.HttpFunction を実装する必要があります。 |
| 4 | インジェクションは Cloud Function 関数クラスの中で動作します。 |
| 5 | これは標準的な Google Cloud Function の実装であり、ここでは何も派手なことはしていません。 |
BackgroundFunction
この BackgroundFunction はストレージイベントによってトリガーされる以外にも、Google Cloud でサポートされているトリガーイベントを使用できます。
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import com.google.cloud.functions.BackgroundFunction;
import com.google.cloud.functions.Context;
import io.quarkus.gcp.function.test.service.GreetingService;
@Named("storageTest") (1)
@ApplicationScoped (2)
public class BackgroundFunctionStorageTest implements BackgroundFunction<BackgroundFunctionStorageTest.StorageEvent> { (3)
@Inject GreetingService greetingService; (4)
@Override
public void accept(StorageEvent event, Context context) throws Exception { (5)
System.out.println("Receive event: " + event);
System.out.println("Be polite, say " + greetingService.hello());
}
//
public static class StorageEvent { (6)
public String name;
}
}
| 1 | @Named アノテーションでは、 quarkus.google-cloud-functions.function プロパティーで使用する CDI Beanに名前を付けることができますが、これはオプションです。 |
| 2 | 関数はCDI Beanでなければなりません。 |
| 3 | これは通常のGoogle Cloud Functionの実装なので、 com.google.cloud.functions.BackgroundFunction を実装する必要があります。 |
| 4 | インジェクションは Cloud Function 関数クラスの中で動作します。 |
| 5 | これは標準的な Google Cloud Function の実装であり、ここでは何も派手なことはしていません。 |
| 6 | これはトリガーのイベントデータがデシリアライズされるクラスです。 |
RawBackgroundFunction
この RawBackgroundFunction は PubSub イベントでトリガーされる以外にも、Google Cloud でサポートされているトリガーイベントを使用することができます。
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import com.google.cloud.functions.Context;
import com.google.cloud.functions.RawBackgroundFunction;
import io.quarkus.gcp.function.test.service.GreetingService;
@Named("rawPubSubTest") (1)
@ApplicationScoped (2)
public class RawBackgroundFunctionPubSubTest implements RawBackgroundFunction { (3)
@Inject GreetingService greetingService; (4)
@Override
public void accept(String event, Context context) throws Exception { (5)
System.out.println("PubSub event: " + event);
System.out.println("Be polite, say " + greetingService.hello());
}
}
| 1 | @Named アノテーションでは、 quarkus.google-cloud-functions.function プロパティーで使用する CDI Beanに名前を付けることができますが、これはオプションです。 |
| 2 | 関数はCDI Beanでなければなりません。 |
| 3 | これは通常のGoogle Cloud Functionの実装なので、 com.google.cloud.functions.RawBackgroundFunction を実装する必要があります。 |
| 4 | インジェクションは Cloud Function 関数クラスの中で動作します。 |
| 5 | これは標準的な Google Cloud Function の実装であり、ここでは何も派手なことはしていません。 |
CloudEventsFunction
CloudEventsFunction is a feature of Cloud Functions gen 2 only.
|
この CloudEventsFunction は Cloud Events Storage イベントによってトリガーされる以外にも、Google Cloud でサポートされている任意のCloud Eventsを使用できます。
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import com.google.cloud.functions.CloudEventsFunction;
import io.cloudevents.CloudEvent;
import io.quarkus.gcp.function.test.service.GreetingService;
@Named("cloudEventTest") (1)
@ApplicationScoped (2)
public class CloudEventStorageTest implements CloudEventsFunction { (3)
@Inject
GreetingService greetingService; (4)
@Override
public void accept(CloudEvent cloudEvent) throws Exception { (5)
System.out.println("Receive event Id: " + cloudEvent.getId());
System.out.println("Receive event Subject: " + cloudEvent.getSubject());
System.out.println("Receive event Type: " + cloudEvent.getType());
System.out.println("Receive event Data: " + new String(cloudEvent.getData().toBytes())); (6)
System.out.println("Be polite, say " + greetingService.hello());
}
}
| 1 | @Named アノテーションでは、 quarkus.google-cloud-functions.function プロパティーで使用する CDI Beanに名前を付けることができますが、これはオプションです。 |
| 2 | 関数はCDI Beanでなければなりません。 |
| 3 | これは通常のGoogle Cloud Functionの実装なので、 com.google.cloud.functions.CloudEventsFunction を実装する必要があります。 |
| 4 | インジェクションは Cloud Function 関数クラスの中で動作します。 |
| 5 | これは標準的な Google Cloud Function の実装であり、 io.cloudevents.CloudEvent を受け取る以外は何も派手なことはしていません。 |
| 6 | Cloud Eventsの中のストレージイベントです。 |
アプリケーションのビルドと Google Cloud へのデプロイ
アプリケーションを構築するには、標準コマンドを使ってパッケージ化します。
quarkus build
./mvnw install
./gradlew build
前のコマンドの結果、 target/deployment リポジトリ内に単一の JAR ファイルが生成されます。このJARファイルにはプロジェクト内のクラスと、依存関係のクラスが含まれています
これで gcloud beta functions deploy コマンドを使って Google Cloud に関数をデプロイすることができるようになります。
|
このコマンドを初めて起動したときには、以下のようなエラーメッセージが表示されることがあります:
これは、Cloud Build がまだ有効化されていないことを意味します。このエラーを解決するには、エラーに表示されている URL を開き指示に従った後、数分待ってからコマンドを再試行してください。 |
HttpFunction
これは HttpFunction を Google Cloud にデプロイするためのコマンドの例です。
gcloud functions deploy quarkus-example-http \
--entry-point=io.quarkus.gcp.functions.QuarkusHttpFunction \
--runtime=java11 --trigger-http --allow-unauthenticated --source=target/deployment
|
エントリーポイントは常に |
|
また、gcloudのコマンドラインで |
このコマンドは、作成したCloud Functions 関数をトリガーするための httpsTrigger.url を出力します。
BackgroundFunction
関数をデプロイする前に、バケットを作成する必要があります。
gsutil mb gs://quarkus-hello
これは BackgroundFunction を Google Cloud にデプロイするためのコマンドの例です。この関数は Storage イベントによってトリガーされるため、 --trigger-event google.storage.object.finalize と --trigger-resource パラメーターに先の手順で作成したバケットの名前を指定する必要があります。
gcloud functions deploy quarkus-example-storage \
--entry-point=io.quarkus.gcp.functions.QuarkusBackgroundFunction \
--trigger-resource quarkus-hello --trigger-event google.storage.object.finalize \
--runtime=java11 --source=target/deployment
|
エントリーポイントは常に |
|
また、gcloudのコマンドラインで |
イベントをトリガーするには、GCS quarkus-hello バケットにファイルを送るか、gcloudコマンドを使ってシミュレートします。
gcloud functions call quarkus-example-storage --data '{"name":"test.txt"}'
--data contains the GCS event, it is a JSON document with the name of the file added to the bucket.
|
RawBackgroundFunction
これは RawBackgroundFunction を Google Cloud にデプロイするコマンドの例です。この関数は PubSub イベントによってトリガーされるので、 --trigger-event google.pubsub.topic.publish と --trigger-resource パラメーターに、先の手順で作成したトピックの名前を指定する必要があります。
gcloud functions deploy quarkus-example-pubsub \
--entry-point=io.quarkus.gcp.functions.QuarkusBackgroundFunction \
--runtime=java11 --trigger-resource hello_topic --trigger-event google.pubsub.topic.publish --source=target/deployment
|
エントリーポイントは常に |
|
また、gcloudのコマンドラインで |
イベントをトリガーするには、 hello_topic トピックにファイルを送信するか、gcloudコマンドを使用してシミュレートします。
gcloud functions call quarkus-example-pubsub --data '{"data":{"greeting":"world"}}'
CloudEventsFunction
CloudEventsFunction is a feature of Cloud Functions gen 2 only.
|
これは CloudEventsFunction を Google Cloud にデプロイするコマンドの例です。この関数は Storage イベントをトリガーとしているので、 --trigger-bucket パラメータにあらかじめ作成した Bucket 名を指定しておく必要があります。
gcloud functions deploy quarkus-example-cloud-event --gen2 \
--entry-point=io.quarkus.gcp.functions.QuarkusCloudEventsFunction \
--runtime=java11 --trigger-bucket=example-cloud-event --source=target/deployment
|
エントリーポイントは常に |
|
また、gcloudのコマンドラインで |
イベントをトリガーするために、GCS example-cloud-event のバケットにファイルを送信することができます。
ローカルでのテスト
関数をローカルでテストする最も簡単な方法は、Cloud Function invoker JAR を使用することです。
以下のコマンドで Maven 経由でダウンロードできます。
mvn dependency:copy \
-Dartifact='com.google.cloud.functions.invoker:java-function-invoker:1.1.1' \
-DoutputDirectory=.
invokerを使用する前に、まず、以下のように関数をビルドする必要があります。
quarkus build
./mvnw install
./gradlew build
HttpFunction
HttpFunction をテストするために、以下のコマンドを使用しローカルで関数を起動することができます。
java -jar java-function-invoker-1.1.1.jar \
--classpath target/google-cloud-functions-1.0.0-SNAPSHOT-runner.jar \
--target io.quarkus.gcp.functions.QuarkusHttpFunction
The --classpath parameter needs to be set to the previously packaged JAR that contains your function class and all Quarkus related classes.
|
エンドポイントは http://localhost:8080 で利用できます。
BackgroundFunction
BackgroundFunction関数の場合は、 io.quarkus.gcp.functions.BackgroundFunction のターゲットクラスでinvokerを起動します。
java -jar java-function-invoker-1.1.1.jar \
--classpath target/google-cloud-functions-1.0.0-SNAPSHOT-runner.jar \
--target io.quarkus.gcp.functions.QuarkusBackgroundFunction
The --classpath parameter needs to be set to the previously packaged JAR that contains your function class and all Quarkus related classes.
|
起動後、HTTP 呼び出しにイベントを含むペイロードを付与することでバックグラウンド関数を呼び出すことができます。
curl localhost:8080 -d '{"data":{"name":"hello.txt"}}'
このコマンドにより、イベント {"name":"hello.txt"} でBackgroundFunctionを呼び出します。これは、 hello.txt をCloud Storageに保存した際のイベントをテストするのと同じです。
RawBackgroundFunction
BackgroundFunction関数の場合は、 io.quarkus.gcp.functions.BackgroundFunction のターゲットクラスでinvokerを起動します。
java -jar java-function-invoker-1.1.1.jar \
--classpath target/google-cloud-functions-1.0.0-SNAPSHOT-runner.jar \
--target io.quarkus.gcp.functions.QuarkusBackgroundFunction
The --classpath parameter needs to be set to the previously packaged JAR that contains your function class and all Quarkus related classes.
|
起動後、HTTP 呼び出しにイベントを含むペイロードを付与することでバックグラウンド関数を呼び出すことができます。
curl localhost:8080 -d '{"data":{"greeting":"world"}}'
このコマンドは、PubSubのBackgroundFunctionを次のPubSubMessageで呼び出します {"greeting":"world"} 。
CloudEventsFunction
CloudEventsFunction is a feature of Cloud Function gen 2 only.
|
CloudEventsFunctionの場合は、 io.quarkus.gcp.functions.QuarkusCloudEventsFunction のターゲットクラスでinvokerを起動します。
java -jar java-function-invoker-1.1.1.jar \
--classpath target/google-cloud-functions-1.0.0-SNAPSHOT-runner.jar \
--target io.quarkus.gcp.functions.QuarkusCloudEventsFunction
The --classpath parameter needs to be set to the previously packaged JAR that contains your function class and all Quarkus related classes.
|
イベントを含むペイロードを持つHTTPコールを介して、CloudEventsFunctionを呼び出すことができます。
curl localhost:8080 \
-X POST \
-H "Content-Type: application/json" \
-H "ce-id: 123451234512345" \
-H "ce-specversion: 1.0" \
-H "ce-time: 2020-01-02T12:34:56.789Z" \
-H "ce-type: google.cloud.storage.object.v1.finalized" \
-H "ce-source: //storage.googleapis.com/projects/_/buckets/MY-BUCKET-NAME" \
-H "ce-subject: objects/MY_FILE.txt" \
-d '{
"bucket": "MY_BUCKET",
"contentType": "text/plain",
"kind": "storage#object",
"md5Hash": "...",
"metageneration": "1",
"name": "MY_FILE.txt",
"size": "352",
"storageClass": "MULTI_REGIONAL",
"timeCreated": "2020-04-23T07:38:57.230Z",
"timeStorageClassUpdated": "2020-04-23T07:38:57.230Z",
"updated": "2020-04-23T07:38:57.230Z"
}'
これにより、 MY_FILE.txt ファイルのイベントでcloud events functionが呼び出されます。