--- Title: Python LambdaのSnapStartとAWS Lambda Powertools Author: sinofseven Web: https://mimemo.io/m/M2rKBGz8xPlD0Em --- ## 自己紹介 - 夏目 祐樹 (ナツメ ユウタ) - クラスメソッド - 製造ビジネステクノロジー部 - 好きなAWS Service - Lambda, DynamoDB, SQS, S3 - 近況 - FF7 Rebirthを100時間以上プレイするもクリアまで行かず --- ## Cold Start --- ## Cold Start ![[9005460307943389] perf-optimize-figure-1](https://mimemo.s3-ap-northeast-1.amazonaws.com/attachment/8c497cf2-dbeb-4943-9a69-3d9c33375fb9.png) 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) ```python 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) ```js { "cache": "2025-02-07 18:19:44.945058+00:00", "now:": "2025-02-07 18:22:03.355189+00:00" } ``` ```js { "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で最新バージョンのみ残す書き方 ```yaml Transform: AWS::Serverless-2016-10-31 Resources: Function: Type: AWS::Serverless::Function DeletionPolicy: Delete Properties: AutoPublishAlias: prod ... ``` --- ## CDKで最新バージョンのみ残す書き方 ```js 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](https://mimemo.s3-ap-northeast-1.amazonaws.com/attachment/43221580-7873-4f2b-8e07-ae387fb5b7e9.png) --- ## 非同期実行のLambda用のIssueとPR作成 (2) ![[9005460264530344] スクリーンショット 2025-02-08 13.49.59](https://mimemo.s3-ap-northeast-1.amazonaws.com/attachment/10494e59-7018-4f06-8001-831cd5b478ac.png) --- ## 非同期実行の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://mimemo.s3-ap-northeast-1.amazonaws.com/attachment/26236e33-891b-4183-a0ce-a05ef76d78ed.png) https://reinvent2024.index.devio.luciferous.app/ --- ## Developers.IO re:Invent 2024 索引 (2) ![[9005460263726526] da98d658537028220befab77c4006e38fab05c9d](https://mimemo.s3-ap-northeast-1.amazonaws.com/attachment/1fa853ff-a8d2-4500-af30-28959ba6f2a4.png)