TL;DR
AWS LambdaでJavaのフレームワーク、たとえばSpringBootなどを使いたいって思ったことありませんか?
結論としては、AWS Lambdaの上に、aws-serverless-java-containerフレームワークというプロキシフレームワークを入れれば比較的簡単に実現可能です。
今日は、そのあたりを、このAWSブログを軽く意訳しつつ書いていきたいと思います。
AWS Open Source Blog Running APIs Written in Java on AWS Lambda
背景
Java開発者は、SpringやSpring BootからJersey、Sparkといった慣れ親しんだフレームワークで開発していることが多いのではないでしょうか。
これらのフレームワークは、Tomcatなどのサーブレットコンテナを用いて、ビルドされたWarやJarをデプロイするか、アプリケーションを内包した実行可能なJarとして利用することができます。
AWSのサーバーレスでは、AWS LambdaとAmazon API GatewayでWEBのバックエンドが構築できますが、Lambdaがコンピュートを担い、API GatewayがRESTの管理を担います。
この記事では、Lambdaで使える、aws-serverless-java-containerフレームワークをご紹介します。
仕組み
簡単に言うと、aws-serverless-java-containerは、Spring、Spring Boot、Jersey、Sparkなどのフレームワークで作られたアプリケーションを、簡単に、最小限のコード変更でAWS Lambda内で実行できるようにするものです。
aws-serverless-java-containerは、Lambdaランタイムと選択したフレームワーク間のプロキシとして機能し、サーブレットエンジンのふりをして、API GatewayからのEventをフレームワークが理解できるリクエストオブジェクトに変換し、アプリケーションからのレスポンスオブジェクトをAPI Gatewayの理解できる形式に変換します。
Spring Boot2をLambdaにのせて独自アプリを構築したい場合は、こちらに詳しい導入方法が紹介されています。
Quick start Spring Boot2
サンプルアプリダウンロード
awslabからaws-serverless-java-containerをcloneしてきましょう。この中に様々なJavaフレームワークのプロキシとサンプルコードが含まれています。
$ git clone https://github.com/awslabs/aws-serverless-java-container.git
独自アプリケーション用のプロキシはこちら
- aws-serverless-java-container-jersey
- aws-serverless-java-container-spark
- aws-serverless-java-container-spring
- aws-serverless-java-container-springboot2
- aws-serverless-java-container-struts2
独自アプリを構築するにはこれらを使えばいいのですが、この記事では簡単のために、Spring Boot2のサンプルを利用したいと思います。
Spring Boot2のLambdaへの導入
まず、以下の前提条件を満たしておきましょう。
まず、mvnコマンドを使って、Javaアプリケーションをビルドしましょう。
$ cd aws-serverless-java-container/samples/springboot2/pet-store/
$ mvn package
mvnコマンドが成功すると、serverless-spring-boot-example-1.0-SNAPSHOT.jar
が、target
ディレクトリにできているはずです。
つぎに、AWS SAMを使って、Lambdaにデプロイするpackageを作ります。<YOUR S3 BUCKET NAME>
には、適当なS3バケット名を指定しておきます。
$ aws cloudformation package --template-file sam.yaml --output-template-file output-sam.yaml --s3-bucket <YOUR S3 BUCKET NAME>
デプロイ用のパッケージができたら、次はいよいよLambdaへのデプロイです。このデプロイによってロジックを処理するAWS Lambdaと、HTTPSリクエストを受け取ってLambdaを呼び出すAPI Gatewayがデプロイされます。
$ aws cloudformation deploy --template-file output-sam.yaml --stack-name ServerlessSpringBootSample --capabilities CAPABILITY_IAM
デプロイが成功すると、以下のコマンドで実際に作られた、APIのエンドポイントを知ることができます。
$ aws cloudformation describe-stacks --stack-name ServerlessSpringBootSample
{
"Stacks": [
{
"StackId": "arn:aws:cloudformation:us-west-2:xxxxxxxx:stack/JerseySample/xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx",
"Description": "Example Pet Store API written with spark with the aws-serverless-java-container library",
"Tags": [],
"Outputs": [
{
"Description": "URL for application",
"OutputKey": "SpringBootPetStoreApi",
"OutputValue": "https://xxxxxxx.execute-api.us-west-2.amazonaws.com/Prod/pets"
}
],
"CreationTime": "2016-12-13T22:59:31.552Z",
"Capabilities": [
"CAPABILITY_IAM"
],
"StackName": "JerseySample",
"NotificationARNs": [],
"StackStatus": "UPDATE_COMPLETE"
}
]
}
OutputValue
に指定されているAPIエンドポイントが、今回デプロイされ起動したAPIのURIになります。
動作確認してみましょう。
$ curl https://xxxxxxx.execute-api.us-west-2.amazonaws.com/Prod/pets
結果のJSONが返ってきたら成功です!
いかがだったでしょうか?サンプルアプリの導入がこんなに簡単にできました。
次のステップに進むには?
Spring Boot2は素晴らしいフレームワークで上の手順に従うことでLambdaにのせて実行させることは簡単にできるのですが、もっと小回りの効く、小さなフレームワークを導入したいといった場合Spark
やMicronaut
にも挑戦してみてください。
また、Lambdaの初回起動時のLatencyが気になるワークロードについてはOracle社が提供しているGraalVMを利用したNative実行も可能です。
MicronautとGraalVMを使ったNative化のサンプルはこちら
Micronaut X GraalVMサンプルペットショップ
この記事の関連情報としてJJUG CCC 2019 Fallの登壇資料がありますので、参考にしてください。