Lambdaが.Net Core2.1に対応しました!!

サーバーレス開発部@大阪の岩田です。 先日AWSのブログでもアナウンスがありましたが、Lambdaが.Net Core2.1に対応しました。

AWS Lambda が、.NET Core 2.1 をサポート

サーバーレス開発部の案件では、現状.Net Coreは使用していないのですが、せっかくなので試しに触ってみました。

環境

検証に使用したローカル環境は下記の通りです。

  • OS: darwin x64
  • .NET Core:2.1.301

.Net Core2.1のLambdaをデプロイしてみる

プロジェクトの作成

まずはAmazon.Lambda.Templatesを使って適当に雛形のLambdaを作成してみます。

dotnet new lambda.S3 --name lambda_s3
テンプレート "Lambda Simple S3 Function" が正常に作成されました。

作成完了です。

デプロイ

早速デプロイしてみます。

cd lambda_s3/src/lambda_s3/
dotnet restore
  /Users/xxxxxx/lambda_s3/src/lambda_s3/lambda_s3.csproj のパッケージを復元しています...
  /Users/xxxxxx/lambda_s3/src/lambda_s3/lambda_s3.csproj の復元が 106.29 ms で完了しました。
  AWSSDK.Core 3.3.24.3 をインストールしています。
  AWSSDK.S3 3.3.18.6 をインストールしています。
  Amazon.Lambda.S3Events 1.0.2 をインストールしています。
  MSBuild ファイル /Users/xxxxxx/lambda_s3/src/lambda_s3/obj/lambda_s3.csproj.nuget.g.props を生成しています。
  MSBuild ファイル /Users/xxxxxx/lambda_s3/src/lambda_s3/obj/lambda_s3.csproj.nuget.g.targets を生成しています。
  /Users/xxxxxx/lambda_s3/src/lambda_s3/lambda_s3.csproj の復元が 4.45 sec で完了しました。
dotnet lambda deploy-function lambda_s3_dotnet21 --function-role xxxxxxx --region ap-northeast-1
Amazon Lambda Tools for .NET Core applications (2.2.0)
Project Home: https://github.com/aws/aws-extensions-for-dotnet-cli, https://github.com/aws/aws-lambda-dotnet

Executing publish command
Deleted previous publish folder
... invoking 'dotnet publish', working folder '/Users/xxxxxx/lambda_s3/src/lambda_s3/bin/Release/netcoreapp2.1/publish'
... publish: .NET Core 向け Microsoft (R) Build Engine バージョン 15.7.179.6572
... publish: Copyright (C) Microsoft Corporation.All rights reserved.
... publish:   /Users/xxxxxx/lambda_s3/src/lambda_s3/lambda_s3.csproj の復元が 53.39 ms で完了しました。
... publish:   /Users/xxxxxx/lambda_s3/src/lambda_s3/lambda_s3.csproj の復元が 28.63 ms で完了しました。
... publish:   lambda_s3 -> /Users/xxxxxx/lambda_s3/src/lambda_s3/bin/Release/netcoreapp2.1/linux-x64/lambda_s3.dll
... publish:   lambda_s3 -> /Users/xxxxxx/lambda_s3/src/lambda_s3/bin/Release/netcoreapp2.1/publish/
Changed permissions on published dll (chmod +r Amazon.Lambda.S3Events.dll).
Changed permissions on published dll (chmod +r AWSSDK.Core.dll).
Changed permissions on published dll (chmod +r AWSSDK.S3.dll).
Changed permissions on published dll (chmod +r lambda_s3.dll).
Changed permissions on published dll (chmod +r Newtonsoft.Json.dll).
Changed permissions on published dll (chmod +r Amazon.Lambda.Core.dll).
Changed permissions on published dll (chmod +r Amazon.Lambda.Serialization.Json.dll).
Zipping publish folder /Users/xxxxxx/lambda_s3/src/lambda_s3/bin/Release/netcoreapp2.1/publish to /Users/xxxxxx/lambda_s3/src/lambda_s3/bin/Release/netcoreapp2.1/lambda_s3.zip
... zipping:   adding: Amazon.Lambda.S3Events.dll (deflated 58%)
... zipping:   adding: lambda_s3.deps.json (deflated 83%)
... zipping:   adding: AWSSDK.Core.dll (deflated 67%)
... zipping:   adding: AWSSDK.S3.dll (deflated 65%)
... zipping:   adding: lambda_s3.runtimeconfig.json (deflated 23%)
... zipping:   adding: lambda_s3.dll (deflated 54%)
... zipping:   adding: Newtonsoft.Json.dll (deflated 60%)
... zipping:   adding: Amazon.Lambda.Core.dll (deflated 57%)
... zipping:   adding: Amazon.Lambda.Serialization.Json.dll (deflated 56%)
... zipping:   adding: lambda_s3.pdb (deflated 32%)
Created publish archive (/Users/xxxxxx/lambda_s3/src/lambda_s3/bin/Release/netcoreapp2.1/lambda_s3.zip).
Creating new Lambda function lambda_s3_dotnet21
New Lambda function created

デプロイ完了です。

確認

マネジメントコンソールから確認してみます。

ランタイム:.Net Core2.1でデプロイできています!

.Net Core2.0のLambdaと比較してみる。

せっかくなので、.Net Core2.0のLambdaと比較してみます。

MSDNのブログに記載されているのですが、.Net Core2.0から.Net Core2.1への変更点として、ネットワーク周りのパフォーマンスが大きく向上しているそうです。

https://blogs.msdn.microsoft.com/dotnet/2018/04/18/performance-improvements-in-net-core-2-1/

Lambdaの処理の中ではDynamoDBやS3など、他のAWSサービスに対してAPIをコールすることが多いので、パフォーマンス向上の恩恵を受けられそうです。 実際に比較してみました。

比較用のコード

先ほど作成された雛形のコードを下記のように修正しました。

public async Task<string> FunctionHandler(S3Event evnt, ILambdaContext context)
{

    try
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();
        for(int i=0;i<10000;i++)
        {
            var response = await this.S3Client.GetObjectMetadataAsync("xxxxx", "xxxxxx");
        }
        sw.Stop();
        return sw.Elapsed.ToString();
    }
    catch(Exception e)
    {
        context.Logger.LogLine(e.Message);
        context.Logger.LogLine(e.StackTrace);
        throw;
    }
}

S3バケットのオブジェクトからメタデータを取得する処理を10,000回実行します。 .Net Core2.0と.Net Core2.1の比較が目的なので、S3バケットやオブジェクトのキーはオンコードでベタ書きしました。

.Net Core 2.1でデプロイ

改めてデプロイします。

dotnet lambda deploy-function lambda_s3_dotnet21 --function-role xxxxxx --region ap-northeast-1 --function-timeout 300

注意点としてタイムアウト時間を300秒に伸ばしています。

.Net Core 2.0でデプロイ

.Net Core2.1でデプロイできたら、今度は.Net Core2.0でデプロイしてみます。 aws-lambda-tools-defaults.jsonlambda_s3.csprojを書き換えて、ターゲットを.Net Core2.0に設定します。

{
  "Information": [
    "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
    "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",

    "dotnet lambda help",

    "All the command line options for the Lambda command can be specified in this file."
  ],

  "profile":"",
  "region" : "",
  "configuration": "Release",
  "framework": "netcoreapp2.0",
  "function-runtime": "dotnetcore2.0",
  "function-memory-size": 256,
  "function-timeout": 300,
  "function-handler": "lambda_s3::lambda_s3.Function::FunctionHandler"
}
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
    <AWSProjectType>Lambda</AWSProjectType>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Amazon.Lambda.Core" Version="1.0.0" />
    <PackageReference Include="Amazon.Lambda.Serialization.Json" Version="1.3.0" />
    <PackageReference Include="Amazon.Lambda.S3Events" Version="1.0.2" />
    <PackageReference Include="AWSSDK.S3" Version="3.3.18.6" />
  </ItemGroup>

  <ItemGroup>
    <DotNetCliToolReference Include="Amazon.Lambda.Tools" Version="2.2.0" />
  </ItemGroup>

</Project>

設定できたらデプロイします。

dotnet lambda deploy-function lambda_s3_dotnet20 --function-role xxxxxx --region ap-northeast-1 --function-timeout 300

比較

両バージョンでデプロイできたら、適当にテストイベントを設定して実行 比較してみます。

.Net Core2.0の場合

.Net Core2.1の場合

.Net Core2.1の方が約30秒程度高速という結果になりました!!

まとめ

Lambdaで.Net Core2.1を試してみました。 サーバーレス開発部では、現状.Net Coreは利用されていないのですが、C#自体はとても良い言語だと思います。

DynamoDBを利用したアプリではRDBとは違い、データの集計処理等はアプリ側で行なう必要がありますが、こういったケースでは.NETのLINQを利用することで、効率良く開発が進められると考えています。 .Net Coreに関してもしっかりとキャッチアップを続けていきたいと思います。