AWS LambdaでJavaのフレームワークを使うには!?


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

独自アプリケーション用のプロキシはこちら

独自アプリを構築するにはこれらを使えばいいのですが、この記事では簡単のために、Spring Boot2のサンプルを利用したいと思います。

Spring Boot2のLambdaへの導入

Spring Boot2 ペットショップサンプル

まず、以下の前提条件を満たしておきましょう。

まず、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にのせて実行させることは簡単にできるのですが、もっと小回りの効く、小さなフレームワークを導入したいといった場合SparkMicronautにも挑戦してみてください。

また、Lambdaの初回起動時のLatencyが気になるワークロードについてはOracle社が提供しているGraalVMを利用したNative実行も可能です。

MicronautとGraalVMを使ったNative化のサンプルはこちら
Micronaut X GraalVMサンプルペットショップ

この記事の関連情報としてJJUG CCC 2019 Fallの登壇資料がありますので、参考にしてください。


サーバーレス時代のJavaについて