Rust の Lambda 関数ハンドラーの定義
注記
「Rust ランタイムクライアント
Lambda 関数ハンドラーは、イベントを処理する関数コード内のメソッドです。関数が呼び出されると、Lambda はハンドラーメソッドを実行します。関数は、ハンドラーが応答を返すか、終了するか、タイムアウトするまで実行されます。
Rust ハンドラーの基本
Lambda 関数コードを Rust 実行ファイルとして記述します。ハンドラー関数コードとメイン関数を実装し、以下のものを含めます。
-
Rust の Lambda プログラミングモデルを実装する crates.io の lambda_runtime
クレート。 -
依存関係には Tokio
を含めます。Lambda 用の Rust ランタイムクライアント は、Tokio を使用して非同期呼び出しを処理します。
例 — JSON イベントを処理する Rust ハンドラー
次の例では、serde_json
use lambda_runtime::{service_fn, LambdaEvent, Error}; use serde_json::{json, Value}; async fn handler(event: LambdaEvent<Value>) -> Result<Value, Error> { let payload = event.payload; let first_name = payload["firstName"].as_str().unwrap_or("world"); Ok(json!({ "message": format!("Hello, {first_name}!") })) } #[tokio::main] async fn main() -> Result<(), Error> { lambda_runtime::run(service_fn(handler)).await }
次の点に注意してください。
-
use
: Lambda 関数に必要なライブラリをインポートします。 -
async fn main
: Lambda 関数コードが実行するエントリポイント。Rust ランタイムクライアントは Tokioを非同期ランタイムとして使用するため、 #[tokio::main]
のメイン関数にアノテーションを付ける必要があります。 -
async fn handler(event: LambdaEvent<Value>) -> Result<Value,
Error
>
: これは Lambda ハンドラーの署名です。関数が呼び出されたときに実行するコードが含まれています。-
LambdaEvent<Value>
: これは、Lambda ランタイムが受け取るイベントと Lambda 関数コンテキストを記述するジェネリックタイプです。 -
Result<Value, Error>
: この関数はResult
タイプを返します。関数が成功すると、結果は JSON 値になります。関数が成功しなかった場合、結果はエラーになります。
-
共有ステートを使用する
Lambda 関数のハンドラーコードとは共有された変数を宣言して変更することができます。これらの変数は、関数がイベントを受け取る前に、初期化フェーズ 中の状態情報をロードするのに役立ちます。
例 — Amazon S3 クライアントを関数インスタンス間で共有
次の点に注意してください。
-
use aws_sdk_s3::Client
: この例では、Cargo.toml
ファイル内の依存関係のリストにaws-sdk-s3 = "0.26.0"
を追加する必要があります。 -
aws_config::from_env
: この例では、Cargo.toml
ファイル内の依存関係のリストにaws-config = "0.55.1"
を追加する必要があります。
use aws_sdk_s3::Client; use lambda_runtime::{service_fn, Error, LambdaEvent}; use serde::{Deserialize, Serialize}; #[derive(Deserialize)] struct Request { bucket: String, } #[derive(Serialize)] struct Response { keys: Vec<String>, } async fn handler(client: &Client, event: LambdaEvent<Request>) -> Result<Response, Error> { let bucket = event.payload.bucket; let objects = client.list_objects_v2().bucket(bucket).send().await?; let keys = objects .contents() .map(|s| s.iter().flat_map(|o| o.key().map(String::from)).collect()) .unwrap_or_default(); Ok(Response { keys }) } #[tokio::main] async fn main() -> Result<(), Error> { let shared_config = aws_config::from_env().load().await; let client = Client::new(&shared_config); let shared_client = &client; lambda_runtime::run(service_fn(move |event: LambdaEvent<Request>| async move { handler(&shared_client, event).await })) .await }
Rust Lambda 関数のコードのベストプラクティス
Lambda 関数をビルドするときは、次のリストのガイドラインに従って、コーディングのベストプラクティスを実行してください。
-
Lambda ハンドラーをコアロジックから分離します。これにより、関数の単体テストが実行しやすくなります。
-
依存関係の複雑さを最小限に抑えます。フレームワークを単純化して、実行環境起動時のロードを高速化します。
-
デプロイパッケージをランタイムに必要な最小限のサイズにします。これにより、呼び出しに先立ってデプロイパッケージをダウンロードして解凍する所要時間が短縮されます。
-
実行環境の再利用を活用して関数のパフォーマンスを向上させます。関数ハンドラー外で SDK クライアントとデータベース接続を初期化し、静的なアセットを
/tmp
ディレクトリにローカルにキャッシュします。関数の同じインスタンスで処理された後続の呼び出しは、これらのリソースを再利用できます。これにより、関数の実行時間が短縮され、コストが節約されます。呼び出し間でデータが漏れるのを防ぐため、実行環境を使用してセキュリティ上の懸念があるユーザーデータ、イベント、またはその他の情報を保存しないでください。関数がハンドラー内のメモリに保存できない変更可能な状態に依存している場合は、ユーザーごとに個別の関数または個別のバージョンの関数を作成することを検討してください。
-
keep-alive ディレクティブを使用して永続的な接続を維持します。Lambda は、時間の経過とともにアイドル状態の接続を消去します。関数を呼び出すときにアイドル状態の接続を再利用しようとすると、接続エラーが発生します。永続的な接続を維持するには、ランタイムに関連付けられている keep-alive ディレクティブを使用します。例については、「Node.js で Keep-alive を使用して接続を再利用する」を参照してください。
-
環境変数を使用して、オペレーショナルパラメータを関数に渡します。たとえば、Amazon S3 バケットに書き込む場合、書き込み先のバケット名はハードコーディングせずに、環境変数として設定します。
-
Lambda 関数では、再帰呼び出しを使用しないでください。関数が自身を呼び出すこともあれば、新たに開始されたプロセスで関数が再度呼び出される可能性もあります。これを行うと意図しないボリュームで関数が呼び出され、料金が急増する可能性があります。意図しない呼び出しがいくつも見つかった場合は、すぐに関数の予約済同時実行数を
0
に設定して、コードを更新している間のすべての関数の呼び出しをスロットリングします。 -
Lambda 関数コードで文書化されていない非公開の API を使用しないでください。AWS Lambda マネージドランタイムでは、Lambda が Lambda の内部 API にセキュリティと機能面の更新を定期的に適用します。これらの内部 API 更新には後方互換性がないことがあり、関数にこれらの非公開 API に対する依存関係がある場合、呼び出しの失敗などの意図しない結果につながります。公開されている API のリストについては、「API リファレンス」を参照してください。
-
冪等性コードを記述します。関数の記述に冪等性コードを使用すると、重複するイベントが同じ方法で処理されるようになります。コードでは、イベントを適切に検証し、重複するイベントを適切に処理する必要があります。詳細については、「Lambda 関数を冪等にするにはどうすればよいですか?
」を参照してください。