Skip to content

Lambdaの書き方

Lambdaの書き方について、Pythonを例に解説します。Lambdaのコードは、通常ハンドラー関数と呼ばれる特定の形式で記述されます。

Lambda関数を作成する際、エントリポイントとなるのがハンドラー関数です。この関数は、イベントソースからトリガーされたときにLambdaサービスによって呼び出されます。ハンドラー関数は以下の2つの引数を取ることが一般的です。

  • event: JSON形式のデータで、Lambda関数を呼び出したイベントソース(例: API GatewayからのHTTPリクエスト、S3からのファイルアップロード通知など)に関する情報が含まれます。
  • context: ランタイム情報、リクエストID、ログストリーム名など、呼び出しに関する情報を提供するオブジェクトです。

Pythonにおけるハンドラー関数の例

Section titled “Pythonにおけるハンドラー関数の例”
import json
def lambda_handler(event, context):
# eventオブジェクトからデータを取得
message = event['message']
# ここにビジネスロジックを記述
response_message = f"Hello from Lambda! Your message was: {message}"
# 処理結果をJSON形式で返す
return {
'statusCode': 200,
'body': json.dumps(response_message)
}

この例では、lambda_handlerがハンドラー関数です。eventからmessageというキーの値を取得し、加工したメッセージを返しています。

  1. コードの記述: 任意の言語(Python, Node.js, Javaなど)で、上記のハンドラー関数を含むコードを記述します。
  2. 依存関係のパッケージング: アプリケーションが外部ライブラリに依存している場合、それらのライブラリをコードと一緒にパッケージングする必要があります。これは通常、ZIPファイルにまとめて行います。
  3. Lambdaへのアップロード: 作成したZIPファイルをAWS Lambdaにアップロードします。AWSマネジメントコンソールやAWS CLISAMなどのツールを使用してアップロードできます。
  4. トリガーの設定: Lambda関数を自動で実行させるためのトリガーを設定します。API GatewayS3CloudWatch Eventsなど、様々なAWSサービスがトリガーとして利用できます。

よくあるユースケースの書き方例

Section titled “よくあるユースケースの書き方例”
  1. API Gatewayからのリクエストを処理する
import json
def api_handler(event, context):
# HTTPリクエストのボディを取得
try:
body = json.loads(event['body'])
name = body.get('name', 'World')
except json.JSONDecodeError:
name = 'World'
# レスポンスを構築
response_body = {
"message": f"Hello, {name}!"
}
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json'
},
'body': json.dumps(response_body)
}
  1. S3イベントを処理する
import json
def s3_handler(event, context):
# S3イベントからバケット名とオブジェクトキーを取得
for record in event['Records']:
bucket = record['s3']['bucket']['name']
key = record['s3']['object']['key']
print(f"New object '{key}' was uploaded to bucket '{bucket}'")
return {
'statusCode': 200,
'body': json.dumps('Successfully processed S3 event')
}

Lambdaの書き方はシンプルですが、その背後にあるサーバーレスアーキテクチャとイベント駆動型の概念を理解することが、効率的な開発の鍵となります。

Lambdaレイヤーは、複数の関数間でコードや依存ライブラリを共有するための便利な方法です。アプリケーションのビジネスロジックは頻繁に更新されても、依存ライブラリはあまり変わらない場合が多いため、レイヤーを使うことでデプロイメントパッケージのサイズを小さく保つことができます。

  • デプロイ時間の短縮: 関数コードのサイズが小さくなるため、アップロードとデプロイにかかる時間が短縮されます。
  • コードの再利用性: 共通のライブラリやカスタムランタイムを複数の関数で共有でき、コードの重複を防ぎます。
  • パッケージングの簡素化: 依存ライブラリを一度だけパッケージングしてレイヤーとしてアップロードすればよいため、開発プロセスがシンプルになります。
  1. ライブラリのインストール: 共有したいライブラリ(例:requests)を特定のディレクトリ(例:python/)にインストールします。

    Terminal window
    mkdir python
    pip install requests -t python/
  2. レイヤーの作成: python/ディレクトリをZIPファイルに圧縮し、AWS Lambdaコンソールからレイヤーとしてアップロードします。

  3. 関数の設定: 既存のLambda関数に作成したレイヤーを追加します。これで、関数コードからimport requestsが可能になります。

Lambdaコンテナは、DockerコンテナイメージをLambda関数としてデプロイできる機能です。これは、複雑な依存関係を持つアプリケーションや、カスタムランタイムが必要な場合に特に強力です。

  • 巨大なパッケージサイズを許容: 通常のZIPファイル(最大250MB)の制限を超えて、最大10GBまでのコンテナイメージをデプロイできます。これにより、機械学習モデルや大規模なデータ処理ライブラリを含むアプリケーションも簡単に扱えます。
  • 柔軟な開発環境: ローカルのDocker環境で、本番環境とほぼ同じ環境を再現して開発・テストができます。
  • 既存のコンテナワークフローとの統合: すでにコンテナベースの開発を行っているチームにとって、既存のツールチェーン(例:Docker Desktop, Docker Compose)をそのまま利用できます。
  1. Dockerfileの作成: Dockerfileで必要なライブラリや依存関係を定義します。

    # Lambdaが提供するベースイメージを使用
    FROM public.ecr.aws/lambda/python:3.9
    # 依存ライブラリをインストール
    COPY requirements.txt ./
    RUN pip install -r requirements.txt
    # 関数コードをコピー
    COPY my_lambda_function.py ./
    # ハンドラー関数を指定
    CMD ["my_lambda_function.lambda_handler"]
  2. イメージのビルドとプッシュ: ECRElastic Container Registry)にコンテナイメージをプッシュします。

  3. Lambda関数の作成: ECRにあるコンテナイメージを指定して、新しいLambda関数を作成します。

コールドスタートとその対策 ❄️

Section titled “コールドスタートとその対策 ❄️”

Lambdaは、リクエストがない間は実行環境を停止することでコストを最適化します。しかし、新しいリクエストが来たときに実行環境をゼロから起動する必要があり、この初期化に要する時間がコールドスタートです。コールドスタートの時間は、関数のサイズ、依存ライブラリの量、選択した言語によって異なり、応答時間を遅延させることがあります。

コールドスタートを軽減する方法

Section titled “コールドスタートを軽減する方法”
  • メモリ割り当ての増量: メモリを増やすと、CPUも比例して増えるため、初期化処理が高速になります。
  • デプロイパッケージの軽量化: 不要なライブラリを含めないようにして、パッケージサイズを小さく保ちます。Lambdaレイヤーを活用することも有効です。
  • プロビジョニングされた同時実行数 (Provisioned Concurrency): 特定の数の関数インスタンスを常時ウォームな状態に保つ機能です。これにより、コールドスタートを実質的に排除できますが、インスタンスをウォームな状態に保つ間、実行時間とは別に料金が発生します。

Lambdaは、デフォルトでリージョンごとに1,000の同時実行数という制限があります。これはアカウント内のすべての関数で共有されるプールです。トラフィックがこの制限を超えると、リクエストはスロットリング(処理が制限されること)され、エラーが発生します。この問題を回避し、システムの安定性を保つために、同時実行数を適切に制御することが重要です。

  • 予約済み同時実行数 (Reserved Concurrency): 特定の関数に最大同時実行数を割り当てる機能です。これにより、予期せぬトラフィックの急増で他の関数がスロットリングされるのを防ぎ、重要な関数の可用性を確保できます。
  • プロビジョニングされた同時実行数 (Provisioned Concurrency): コールドスタート対策として先述した機能でもありますが、これは最小同時実行数を確保する役割も果たします。

環境変数とSecrets Manager/Parameter Storeの活用

Section titled “環境変数とSecrets Manager/Parameter Storeの活用”

Lambdaの環境変数は、コードを変更することなく関数の動作を調整できるキーと値のペアです。データベース接続文字列、APIキー、AWSリソース名など、環境(開発、ステージング、本番)によって異なる設定値を管理するのに最適です。

  • Secrets Manager: データベースの認証情報、APIキー、OAuthトークンなどを安全に保存、管理、取得するための専用サービスです。
  • Systems Manager Parameter Store: 設定データや機密情報をキーと値のペアで保存するサービスです。

これらのサービスを活用することで、機密情報が環境変数として平文で保存されることを防ぎ、セキュリティを大幅に向上させることができます。