メニュー
AWS Lambda
開発者ガイド

Lambda 関数ハンドラー (C#)

Lambda 関数を作成する際、サービスがユーザーに代わって関数を実行するときに AWS Lambda が呼び出すことができるハンドラーを指定します。

Lambda 関数ハンドラーをクラスのインスタンスまたは静的メソッドとして定義します。Lambda コンテキストオブジェクトへのアクセスが必要な場合は、ILambdaContext. 型のメソッドパラメータを定義します。

Copy
returnType handler-name(inputType input, ILambdaContext context) { ... }

構文では、以下の点に注意してください。

  • inputType – ハンドラーの最初のパラメーターはハンドラーへの入力です。このパラメーターには、イベントデータ (イベントソースによって発行される) またはユーザーが提供するカスタム入力 (文字列やカスタムデータオブジェクトなど) を指定できます。

  • returnType – Lambda 関数を同期的に呼び出す (RequestResponse 呼び出しタイプを使用) 場合は、サポートされているいずれかのデータ型を使用して関数の出力を返すことができます。たとえば、Lambda 関数をモバイルアプリケーションのバックエンドとして使用する場合、これを同期的に呼び出しています。出力データ型は JSON にシリアル化されます。

    Lambda 関数を非同期的に呼び出す (Event 呼び出しタイプを使用) 計画の場合、returnTypevoid である必要があります。たとえば、Amazon S3、Amazon Kinesis、Amazon SNS などのイベントソースとともに AWS Lambda を使用する場合、これらのイベントソースは Event 呼び出しタイプを使用して Lambda 関数を呼び出します。

ストリームの処理

System.IO.Stream タイプのみ入力パラメータとしてデフォルトでサポートされています。

たとえば、次の C# コードの例を考えてみます。

Copy
using System.IO; { namespace Example public class Hello { public Stream MyHandler(Stream stream) { //function logic } }

例の C# コードでは、最初のパラメータはハンドラー (MyHandler) の入力であり、イベントデータ (Amazon S3 などのイベントソースによって発行)、Stream など指定するカスタム入力 (この例のように)、または任意のカスタムデータオブジェクトとすることができます。出力は Stream 型となります。

標準のデータ型の処理

ここに示されているそのほかの型は、すべてシリアライザーを指定する必要があります。

  • .NET プリミティブ型 (文字列、整数など)。

  • コレクションとマップ - IList、IEnumerable、IList<T>、Array、IDictionary、IDictionary<TKey, TValue>

  • POCO (Plain old CLR objects) 型

  • 定義済み AWS イベントタイプ

  • 非同期の呼び出しの際、戻り型は Lambda により無視されます。このような場合、戻り型を void に設定することもできます。

  • .NET 非同期プログラミングを使用している場合、戻り型は Task および Task<T> 型で async および await キーワードを使用できます。詳細については、「AWS Lambda で C# 関数の Async を使用する」を参照してください。

関数の入力および出力パラメータが System.IO.Stream 型でない限り、シリアル化する必要があります。AWS Lambda は、アプリケーションのアセンブリレベルまたはメソッドレベルで適用できるデフォルトのシリアライザーを提供します。または、ILambdaSerializer インターフェイスを実装して独自に定義することもできます。このインターフェイスは、Amazon.Lambda.Core ライブラリで提供されています。詳細については、「デプロイパッケージの作成 (C#)」を参照してください。

メソッドにデフォルトのシリアライザー属性を追加するには、最初に project.json ファイルの Amazon.Lambda.Serialization.Json に依存関係を追加します。

Copy
{ "version": "1.0.0-*", "dependencies":{ "Microsoft.NETCore.App": { "type": "platform", "version": "1.0.1" }, "Amazon.Lambda.Serialization.Json": "1.0.0" }, "frameworks": { "netcoreapp1.0": { "imports": "dnxcore50" } } }
以下の例では、あるメソッドでデフォルトの Json.NET シリアライザーを指定し、別のメソッドで選択したものを指定することで、柔軟な利用が可能であることを示しています。

Copy
public class ProductService{ [LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))] public Product DescribeProduct(DescribeProductRequest request) { return catalogService.DescribeProduct(request.Id); } [LambdaSerializer(typeof(MyJsonSerializer))] public Customer DescribeCustomer(DescribeCustomerRequest request) { return customerService.DescribeCustomer(request.Id); } }

ハンドラー署名

Lambda 関数を作成する場合、呼び出すコードをどこで探すか AWS Lambda に指示するハンドラー文字列を指定する必要があります。C# では、次の形式になります。

ASSEMBLY::TYPE::METHOD where:

  • ASSEMBLY は、アプリケーションの .NET アセンブリファイルの名前です。.NET Core CLI を使用してアプリケーションを構築する場合、project.json で buildOptions.outputName 設定を使用してアセンブリ名を設定していない場合、ASSEMBLY 名が project.json ファイルを含むフォルダの名前になります。詳細については、「.NET Core CLI」を参照してください。この場合、フォルダ名は HelloWorldApp だと仮定します。

  • TYPE は、NamespaceClassName からなるハンドラー型の正式名称となります。 この場合、Example.Hello です。

  • METHOD は、関数ハンドラー名で、この場合 MyHandler です。

最終的に、署名は次の形式になります。 Assembly::Namespace.ClassName::MethodName

再び次の例を考えます。

Copy
using System.IO; { namespace Example public class Hello { public Stream MyHandler(Stream stream) { //function logic } }

ハンドラー文字列は次のようになります。 HelloWorldApp::Example.Hello::MyHandler

この C# コードを使用して Lambda 関数を作成する手順については、「ステップ 2.4: (オプション) C# で Lambda 関数を作成する」を参照してください。

重要

ハンドラー文字列で指定されたメソッドが過負荷になっている場合は、Lambda が呼び出す必要があるメソッドの正確な署名を指定する必要があります。複数の (過負荷の) 署名の中から選択する必要がある場合、AWS Lambda は有効な署名を拒否します。

Lambda 関数ハンドラーの制限

ハンドラー署名にいくつかの制限があることに注意してください

  • unsafe コンテキストは、ハンドラーメソッドとその依存関係の内部で使用できますが、ハンドラー署名に unsafe がなくポインタ型を使用できない場合があります。詳細については、unsafe (C# リファレンス) を参照してください。

  • params キーワードを使用して可変数のパラメータを渡さなかったり、可変数のパラメータをサポートするために使用する入力パラメータまたは戻りパラメータとして ArgIterator を使用できない場合があります。

  • ハンドラーは汎用メソッドでないことがあります (例: IList<T> Sort<T>(IList<T> input))。

  • async void 署名を持つ Async ハンドラーはサポートされていません。

AWS Lambda で C# 関数の Async を使用する

大容量ファイルを Amazon S3 にアップロードする、DynamoDB から大量のストリームのレコードを読み込むなど、Lambda 関数で長時間実行するプロセスが必要になることがわかっている場合は、async/await パターンを利用できます。この署名でハンドラーを作成することにより、Lambda は関数を同期的に実行し、実行が完了するのに最大 5 分間待ってから戻るかタイムアウトになります。以下に例を示します。

Copy
public async Task<Response> ProcessS3ImageResizeAsync(SimpleS3Event input) { var response = await client.DoAsyncWork(input); return response; }

このパターンを使用する場合は、いくつかの考慮事項を検討してください。

  • AWS Lambda は async void メソッドをサポートしません。

  • await 演算子を実装しないで非同期 Lambda 関数を作成すると、.NET がコンパイラの警告を出し、予期しない動作が発生します。たとえば、ある非同期アクションは実行され、他の非同期アクションは実行されない、または関数の実行が完了する前に一部の非同期アクションが完了しない、などです。

    Copy
    public async Task ProcessS3ImageResizeAsync(SimpleS3Event event) // Compiler warning { client.DoAsyncWork(input); }
  • Lambda 関数は複数の非同期呼び出しを含めることができ、また並行で呼び出すことができます。複数のタスクを使用するため、Task.WaitAll および Task.WaitAny メソッドを使用できます。Task.WaitAll メソッドを使用するには、配列としてオペレーションのリストをメソッドに渡します。以下の例では、配列へ一部の操作を含めるのを怠ると、その操作が完了する前に呼び出しが返されることに注意してください。

    Copy
    public async Task SaveAsync(Profile profile) { var s3Save = s3.SaveImage(profile.image); var ddbSave = ddb.SaveAttributes(profile.Attributes); var ddbSave2 = ddb.SaveConnections(profile.connections); // Lambda will return before this call completes // No compiler warnings return await Task.WaitAll(new Task[]{ s3Save, ddbSave }); // Did not "await" for ddbSave2 }

    Task.WaitAny メソッドを使用するには、配列としてオペレーションのリストを再度メソッドに渡します。最初の操作が完了すると、他がまだ実行中でも呼び出しがすぐに返されます。

    Copy
    public async Task<SearchResult> SearchAsync(Query q) { var siteSearch1 = site1.SearchAsync(q); var siteSearch2 = site2.SearchAsyc(q); var siteSearch3 = site3.SearchAsync(q); var tasks[] = new Task[]{siteSearch1, siteSearch2, siteSearch3}; var index = await Task.WaitAny(tasks); // Returns as soon as any of the tasks complete, other task may run in background return tasks[index].Result; }

    上記の理由により、Task.WaitAny の使用はお勧めしません。