Python LambdaのSnapStartとAWS Lambda Powertools

自己紹介

  • 夏目 祐樹 (ナツメ ユウタ)
  • クラスメソッド
    • 製造ビジネステクノロジー部
  • 好きなAWS Service
    • Lambda, DynamoDB, SQS, S3
  • 近況
    • FF7 Rebirthを100時間以上プレイするもクリアまで行かず

Cold Start

Cold Start

[9005460307943389] perf-optimize-figure-1

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-runtime-environment.html#cold-start-latency

  • AWS公式の考え方ではMicro VMの作成までがコールドスタート
    • 再実行時はハンドラの実行から
    • 広義の考え方ではコードの初期化も含める

Cold Start

  • どうしてもコードの初期化で初回の実行は遅くなる
    • Pythonのboto3の読み込みでも1秒くらいかかる
      • Pandasとか重いライブラリを読めばもっとかかる
  • GoやRustなどシングルバイナリを生成するような言語ではコールドスタートもウォームスタートも大した差にはならない

ユーザーのくふう (1)

  • 手動ウォームアップ
    • 何らかの手段でLambdaを実行させCold Startを回避する
    • ただし
      • 手動ウォームアップの実行中にリクエストが来たらCold Startが起きる
      • 事前に立ち上げた数よりも多いリクエストが来たらCold Startが起きる

ユーザーのくふう (2)

  • Lambdalith (Monolithic function)
    • 1つのLambdaで複数のイベントを処理する
    • 例えば、APIで複数のパスを一つのLambdaで処理する
    • ただし、Cold Startを多少抑制できる程度

AWSのくふう (1)

  • Provisioned Concurrency
    • AWSによる自動ウォームアップ
    • ただし
      • 設定した実行数よりも多いリクエストが来たらCold Startが起きる
      • ウォームアップしている期間についても課金される

AWSのくふう (2)

  • Snap Start (Java)
    • re:Invent 2022で発表された機能
    • Java 11以降で使用可能
    • コードの初期化済みの環境をキャッシュし、そこから実行することで広義のコールドスタートを高速化する

Pythonと.NETでSnapStartのサポートを開始

AWSのくふう (3)

  • SnapStart (Python, .NET)
    • 2024/11/18から利用できるようになった
    • Python 3.12 以降と .NET 8以降で使用可能

SnapStartの特徴

  • 初期化された実行環境のメモリとディスク状態のFirecracker microVMのスナップショットを保存し、それを再利用することで初回実行を高速化する
  • スナップショットの保存はLambda関数のバージョン発行時
  • 使用できるリージョンは9つ
    • バージニア北部, オハイオ, オレゴン, シンガポール, シドニー, 東京, フランクフルト, アイルランド, ストックホルム

SnapStartの課金体系

  • Pythonと.NETでは使用に料金がかかる (Javaは無料)
  • Lambda関数のバージョン毎に課金される
  • 課金体系は二つ
    • キャッシュの保存期間
      • 最低3時間, 以後ミリ秒単位で課金
      • USD 0.0000015046/GB*秒
      • USD 3.9540888/GB*月 (730h/月)
    • キャッシュのレストア回数
      • USD 0.0001397998/GB*回
      • 7153.1回*GB/USD

Python RuntimeのSnapStart (1)

  • Handlerに設定しているPythonファイルをインポートしてから、キャッシュが作成される
    • そのためグローバル領域での処理は行われる

Python RuntimeのSnapStart (2)

import json
from datetime import datetime, timezone

dt_cache = datetime.now(timezone.utc)


def lambda_handler(event, context):
    data = {
        "cache": str(dt_cache),
        "now:": str(datetime.now(timezone.utc))
    }
    text = json.dumps(data)
    print(text)
    return data

Python RuntimeのSnapStart (3)

{
    "cache": "2025-02-07 18:19:44.945058+00:00",
    "now:": "2025-02-07 18:22:03.355189+00:00"
}
{
    "cache": "2025-02-07 18:19:44.945058+00:00",
    "now:": "2025-02-07 18:22:13.156636+00:00"
}

Python RuntimeのSnapStart (4)

  • グローバル領域でデータを取得するように書けば、事前に大きなデータをダウンロードしておくこともできる
    • バージョン発行時に取得するので、動的に何かを取得するようなことでは注意が必要
  • バージョン発行時なので環境変数も保持されている

Python RuntimeのSnapStartの注意点

  • SnapStartのキャッシュ課金はLambda関数のバージョン毎に行われる
    • バージョンを保存するか削除するかをきちんと管理しないと、アップデートのたびに料金が増えていく

SAMで最新バージョンのみ残す書き方

Transform: AWS::Serverless-2016-10-31

Resources:
  Function:
    Type: AWS::Serverless::Function
    DeletionPolicy: Delete
    Properties:
      AutoPublishAlias: prod
      ...

CDKで最新バージョンのみ残す書き方

const myFunction = new lambda.Function(this, "cdk-latest-version", {
  runtime: lambda.Runtime.PYTHON_3_13,
  handler: "main.handler",
  code: lambda.Code.fromAsset(path.join(__dirname, "../src")),
  currentVersionOptions: {
    removalPolicy: cdk.RemovalPolicy.DESTROY,
  },
});
myFunction.addAlias("prod");

Terrafromで最新バージョンのみ残す書き方

  • 残念ながら設定方法を見つけることはできなかった
  • Ephemeral Resource: aws_lambda_invocationを使って、バージョン発行後にLambdaを動かして過去のバージョンを削除刺せる必要がある

SnapStartのPython対応を見て思ったこと

  • SnapStartを使用するLambda関数が増えれば増えるほど課金額が増えていく
  • 一つのLambdaに複数の処理を行わせるLambdalithの有用性が高まった

Lambdalith (Monolithic Lambda Function)

  • API GatewayのバックエンドのLambdaを一つにまとめるのは前から行われて生きた
    • Pythonでは Flask + aws-wsgiを使う例を見たことある人がいるかもしれない
    • ただ、外部ライブラリを使うのでLayerかデプロイパッケージに含める必要がある

AWS Lambda Powertools

AWS Lambda Powertools

  • AWSが公式に提供しているOSS
  • Lambdaで使える便利ツール群
    • Python以外の言語もある
  • Public Layerが用意されているため簡単に使える
  • LoggerやValidation, Event Source Data Classesなど便利なものがいっぱいある

EventHandler - AWS Lambda Powertools

  • 端的に言うとLambdalithを作りやすくするための仕組み
  • 大きく分けると
    • REST API
      • API Gateway (REST, HTTP), ALB, Lambda Function URL, VPC Lattice
    • GraphQL API
    • Agent for Amazon Bedrock

非同期実行のLambda用のIssueとPR作成 (1)

[9005460264645687] スクリーンショット 2025-02-08 13.47.54

非同期実行のLambda用のIssueとPR作成 (2)

[9005460264530344] スクリーンショット 2025-02-08 13.49.59

非同期実行のLambda用のIssueとPR作成 (3)

  • DeepLによる翻訳と一部抜粋
    • この問題に関しては、私はこのアイデアがとても気に入っていて、2025年のロードマップで議論しているところです。
    • これは、例えばEventBridgeを扱っていて、いくつかのイベントに対して一つのLambdaを使いたい人たちの生活を楽にするだろう。
    • この新しいユーティリティには多くの利点があると思うし、2025年にリリースできたらクールだと思う。

非同期実行のLambda用のIssueとPR作成 (4)

  • 冬休みの自由研究として、プロトタイプを実装
  • 今は単体テストを頑張って書いてる
    • Event Source Data Classes用のイベントデータがあるので単体テストでも割となんとかなる
    • ただし物量が多い

非同期実行のLambda用のIssueとPR作成 (5)

  • 非同期実行用のLambdaが片付いたら
    • イベントソースマッピングのトリガー用のEventHandlerを作ろうかと思ってる
      • 非同期実行用のLambdaの実装で色々意見もらうだろうから、そのあとでIssueを作ろうと思ってる

おまけ

Developers.IO re:Invent 2024 索引 (1)

[9005460263786569] スクリーンショット 2025-02-08 14.02.09

https://reinvent2024.index.devio.luciferous.app/

Developers.IO re:Invent 2024 索引 (2)

[9005460263726526] da98d658537028220befab77c4006e38fab05c9d

END

Close