Spring Native の sampleアプリを Serverlessでデプロイして lambdaで動かす
モチベーション
大量リクエストを低コストでさばく AWS Lambda 関数を JVM で実現 と言う記事 が 2021-10-05 に builders.flash で書かれていました。私は現場でECS上で動くSpringアプリケーションの運用保守をしていますが、その経験から見るとこの記事に書かれている事はとても魅力的に見えます。この記事に端を発し類似する記事をいくつか調べると以下の事が実現できると言う事が書かれています。
- GraalVM の native-image と呼ばれる技術 を使いJava アプリのネイティブ化する事で省メモリ、高速を両立する
- lambdaで 動かす事でスパイクアクセスにも対応できる、またコストも抑えられる
- 月間数十億のリクエストのサービスを支えている事例がある
そこで実際にSpringアプリケーションをlambdaで動かしてみたいと思いましたが、そのやり方が簡単に分かる記事がなかなか見つかりません。(筆者はインフラエンジニアであり、Springアプリケーションの知識に乏しい事にも原因があるかもしれません)
色々と調査・検証した結果、Springアプリケーションをネイティブ化、Serverlessで API Gateway + lambdaをデプロイし、Hello world的な事が実行できたのでその内容を記事に致します。
何をするか
- Spring Native の sample アプリ cloud-function-aws を Serverless でデプロイし動作確認をします
- 同アプリにhandlerを追加しそれを同様に Serverless でデプロイし動作確認をします
なお作業環境はMacです。
前提条件
- 作業環境に以下のソフトウェアがインストールされている
- Docker for Desktop
- Serverless
- AWSアカウントがあり作業環境からアクセスできる
検証内容
ソースを取得
git clone https://github.com/spring-projects-experimental/spring-native.git
cd spring-native/samples/cloud-function-aws
ビルド
README -> Build project (MAC users) の通りに実行しNativeイメージをビルドするとzipファイルが作成されます
cd ../../
./run-dev-container.sh
cat /etc/os-release
# Ubuntu OSになっています
cd samples/cloud-function-aws
./build.sh
# 3:35
exit
# コンテナから抜けます
cd samples/cloud-function-aws
ls -ltr target/cloud-function-aws-0.0.1-SNAPSHOT-native-zip.zip
# zipファイルができています
前述の記事にも書かれていますが、ネイティブ化は起動が早くなりますがビルドには時間がかかります
Serverless設定、デプロイ
serverless.yml を作成します。(Githubで見つけたこちらの内容を参考にしました)
frameworkVersion: '3'
service: cloud-function-demo
provider:
lambdaHashingVersion: 20201221
name: aws
stackName: cloud-function-aws
apiName: cloud-function-aws
region: ap-northeast-1
runtime: provided
memorySize: 128
timeout: 3
tracing:
lambda: true
apiGateway: true
package:
individually: true
functions:
NameUppercase:
name: name-uppercase
handler: nameUppercaser
package:
artifact: ./target/cloud-function-aws-0.0.1-SNAPSHOT-native-zip.zip
events:
- http:
integration: lambda
path: /name-uppercase
method: post
request:
template:
text/plain: '{ "name": "$input.body" }'
デプロイします。
sls deploy
動作確認
curl -X POST -H 'Content-Type: text/plain' https://rjd3qmhu4k.execute-api.ap-northeast-1.amazonaws.com/dev/name-uppercase -d 'hello world!'
# "hi HELLO WORLD!!"
handlerの追加
1つのアプリケーションに複数のhandlerがあっても問題なく動作するのかが気になりましたが、
spring cloud function の sample に function-sample-aws-routing があったのでできそうだと思い確認しました
cd src/main/java/com/example/demo/
cp NameUppercaser.java NameLowercaser.java
sed -i -e "s/Upper/Lower/g" NameLowercaser.java
cd ../../../../../..
ビルド
cd ../../
./run-dev-container.sh
cd samples/cloud-function-aws
./build.sh
exit
cd samples/cloud-function-aws
serverless.ymlに追記
NameLowercase:
name: name-lowercase
handler: nameLowercaser
package:
artifact: ./target/cloud-function-aws-0.0.1-SNAPSHOT-native-zip.zip
events:
- http:
integration: lambda
path: /name-lowercase
method: post
request:
template:
text/plain: '{ "name": "$input.body" }'
デプロイ
sls deploy
動作確認
curl -X POST -H 'Content-Type: text/plain' https://rjd3qmhu4k.execute-api.ap-northeast-1.amazonaws.com/dev/name-uppercase -d 'hello world!'
# "hi HELLO WORLD!!"
curl -X POST -H 'Content-Type: text/plain' https://rjd3qmhu4k.execute-api.ap-northeast-1.amazonaws.com/dev/name-lowercase -d 'HELLO WORLD!'
# "hi hello world!!"
無事動作確認する事ができました!
後片付け
Serverlessを使ったので後片付けも簡単です
sls remove
今回の記事は以上となります。参考になれば嬉しいです。
Discussion