AWS Lambda SnapStart を試してみる

エキサイト株式会社メディア開発の佐々木です。

Advent Calendarの季節が今年もやってきました。
昨年同様、エキサイトホールディングス Advent Calendarで毎日投稿される予定です。 様々な話題が投稿されるのでぜひ閲覧してみてください!

qiita.com

AWS Lambda Javaにおけるコールドスタートを解決する方法として、SnapStartが発表されました。 New – Lambda SnapStart で Lambda 関数を高速化 | Amazon Web Services ブログ

Javaが起動するときに裏側で行われている処理を事前にキャッシュしておいて、起動を速くするもののようです。(CRaC Project)https://wiki.openjdk.org/display/cracの成果物も絡んでるようです。さっそく試してみましょう。

前提

Java

$ java --version
openjdk 11.0.17 2022-10-18 LTS
OpenJDK Runtime Environment Corretto-11.0.17.8.1 (build 11.0.17+8-LTS)
OpenJDK 64-Bit Server VM Corretto-11.0.17.8.1 (build 11.0.17+8-LTS, mixed mode)

Gradle

$ ./gradlew --version

------------------------------------------------------------
Gradle 7.3.3
------------------------------------------------------------

Build time:   2021-12-22 12:37:54 UTC
Revision:     6f556c80f945dc54b50e0be633da6c62dbe8dc71

Kotlin:       1.5.31
Groovy:       3.0.9
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          11.0.17 (Amazon.com Inc. 11.0.17+8-LTS)
OS:           Mac OS X 12.5 aarch64

AWS SAM CLI

$ sam --version
SAM CLI, version 1.66.0

AWS SAM Project テンプレート生成

AWS SAM CLIにてプロジェクトテンプレートを生成します。

$ sam init --runtime java11 
Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: `
Error: '`' is not one of '1', '2'.
Choice: 1

Choose an AWS Quick Start application template
        1 - Hello World Example
        2 - Infrastructure event management
        3 - Multi-step workflow
Template: 1

Based on your selections, the only Package type available is Zip.
We will proceed to selecting the Package type as Zip.

Which dependency manager would you like to use?
        1 - gradle
        2 - maven
Dependency manager: 1

Would you like to enable X-Ray tracing on the function(s) in your application?  [y/N]: y
X-Ray will incur an additional cost. View https://aws.amazon.com/xray/pricing/ for more details

Project name [sam-app]: sam-sample-app

Cloning from https://github.com/aws/aws-sam-cli-app-templates (process may take a moment)

    -----------------------
    Generating application:
    -----------------------
    Name: sam-sample-app
    Runtime: java11
    Architectures: x86_64
    Dependency Manager: gradle
    Application Template: hello-world
    Output Directory: .
    
    Next steps can be found in the README file at ./sam-sample-app/README.md
        

    Commands you can use next
    =========================
    [*] Create pipeline: cd sam-sample-app && sam pipeline init --bootstrap
    [*] Validate SAM template: cd sam-sample-app && sam validate
    [*] Test Function in the Cloud: cd sam-sample-app && sam sync --stack-name {stack-name} --watch

今回は、Hello World Exampleテンプレート、Gradleでつくります。

SnapStartの適用

SnapStartを適用するために、template.yamlを修正します。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-sample-app

  Sample SAM Template for sam-sample-app

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 20
    MemorySize: 128

Resources:
  SnapStartFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: HelloWorldFunction
      Handler: helloworld.App::handleRequest
      Runtime: java11
      Architectures:
        - x86_64
      MemorySize: 1024
      Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object
        Variables:
          PARAM1: VALUE
          JAVA_TOOL_OPTIONS: -XX:+TieredCompilation -XX:TieredStopAtLevel=1 # More info about tiered compilation https://aws.amazon.com/blogs/compute/optimizing-aws-lambda-function-performance-for-java/
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /snapStart-hello
            Method: get
      AutoPublishAlias: SnapStart      ## <- 追加
      SnapStart:                                     ## <-  追加
        ApplyOn: PublishedVersions   ## <- 追加
  NonSnapStartFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: HelloWorldFunction
      Handler: helloworld.App::handleRequest
      Runtime: java11
      Architectures:
        - x86_64
      MemorySize: 1024
      Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object
        Variables:
          PARAM1: VALUE
          JAVA_TOOL_OPTIONS: -XX:+TieredCompilation -XX:TieredStopAtLevel=1 # More info about tiered compilation https://aws.amazon.com/blogs/compute/optimizing-aws-lambda-function-performance-for-java/
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /nonSnapStart-hello
            Method: get
Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"

3行追加が必要なので、追加します。

Build & Deploy

修正が終わったら BuildとDeployを行います。

## AWS SAM でビルドする
$ sam build


## AWS SAM CLI でデプロイ
$ sam deploy --guided 

Configuring SAM deploy
======================

        Looking for config file [samconfig.toml] :  Not found

        Setting default arguments for 'sam deploy'
        =========================================
        Stack Name [sam-app]: sam-sample-app
        AWS Region [ap-northeast-1]: ^CAborted!
70-63165:sam-sample-app kohei.sasaki$ sam deploy --guided --profile sam-user

Configuring SAM deploy
======================

        Looking for config file [samconfig.toml] :  Not found

        Setting default arguments for 'sam deploy'
        =========================================
        Stack Name [sam-app]: sam-sample-app
        AWS Region [ap-northeast-1]: 
        #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
        Confirm changes before deploy [y/N]: y
        #SAM needs permission to be able to create roles to connect to the resources in your template
        Allow SAM CLI IAM role creation [Y/n]: y
        #Preserves the state of previously provisioned resources when an operation fails
        Disable rollback [y/N]: y
        HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y
        Save arguments to configuration file [Y/n]: y
        SAM configuration file [samconfig.toml]: 
        SAM configuration environment [default]: 

Deploy this changeset? [y/N]: y

2022-12-20 09:28:43 - Waiting for stack create/update to complete
....
....
....


Key                 HelloWorldApi                                                                                                                                                                                                                                                                                                                                           
Description         API Gateway endpoint URL for Prod stage for Hello World function                                                                                                                                                                                                                                                                                        
Value               https://xxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/                                                                                                                                                                                                                                                                                 

これでAWS Lambdaにデプロイできました。簡単ですね。

AWS コンソールの確認

コンソールを確認すると、SnapStartの情報が載っていました。

  • SnapStart有効の場合
    有効の場合は下記の記載になっています。
SnapStart情報
PublishedVersions
  • SnapStart無効の場合
    SnapStart無効化
    無効の下記の記載になっています。
SnapStart情報
None

SnapStartが効いているかの確認

SnapStartが効いているかを確認します。

それぞれをリクエストして、ログを確認します。

  • SnapStart有効時のログ ログには、 Restore Durationとログに記載されます。
REPORT RequestId: 62d65395-279b-44f5-b1ca-623b3f829290   Duration: 1767.52 ms    Billed Duration: 1924 ms    Memory Size: 1024 MB    Max Memory Used: 96 MB  Restore Duration: 228.74 ms
  • SnapStart無効時のログ ログには Init Durationとログに記載されます。
REPORT RequestId: 4a5a5b30-95a8-4123-abcf-598392e4275e   Duration: 1744.10 ms    Billed Duration: 1745 ms    Memory Size: 1024 MB    Max Memory Used: 109 MB Init Duration: 398.41 ms

まとめると下記になります。

SnapStart有効 SnapStart無効
[Restore/Init]Duration 228.74 ms 398.41 ms
Duration 1767.52 ms 1744.10 ms

Restore/Initに関しては、SnapStartの効果で、170ms近く短縮されていますが、トータルのDurationだと、20msくらい増えています。現時点ではあんまり効果を感じられていない感じです。

まとめ

AWS LambdaにてSnapStartの確認をしてみました。コールドスタートによるハンデが顕著になる部分は速くはなっていましたが、全体的に大幅は高速化は、今回は体感できませんでした。HelloWorldくらいのアプリケーションだと、効果が薄いのかもしれません。今後の改善に期待したいところになります。

最後に

エキサイトではフロントエンジニア、バックエンドエンジニア、アプリエンジニアを随時募集しております。長期インターンも歓迎していますので、興味があれば連絡いただければと思います。

カジュアル面談はこちらになります! meety.net

募集職種一覧はこちらになります!(カジュアルからもOK) www.wantedly.com