네이티브 런타임 형식으로 .NET Lambda 함수 코드 컴파일
.NET 8은 네이티브 사전(AOT) 컴파일을 지원합니다. 네이티브 AOT를 사용하면 Lambda 함수 코드를 네이티브 런타임 형식으로 컴파일할 수 있으므로 런타임에 .NET 코드를 컴파일할 필요가 없습니다. 네이티브 AOT 컴파일은 .NET에서 작성하는 Lambda 함수의 콜드 스타트 시간을 줄일 수 있습니다. 자세한 내용은 AWS Compute Blog의 Introducing the .NET 8 runtime for AWS Lambda
Lambda 런타임
네이티브 AOT 컴파일을 사용하여 Lambda 함수 빌드를 배포하려면 관리형 .NET 8 Lambda 런타임을 사용합니다. 이 런타임은 x86_64 및 arm64 아키텍처의 사용을 모두 지원합니다.
AOT를 사용하지 않고 .NET Lambda 함수를 배포할 경우 애플리케이션이 먼저 중간 언어(IL) 코드로 컴파일됩니다. 런타임의 Just-in-Time(JIT) 컴파일러는 Lambda 런타임에 IL 코드를 가져와 필요에 따라 기계 코드로 컴파일합니다. 네이티브 AOT로 미리 컴파일된 Lambda 함수를 사용하면 함수를 배포할 때 코드를 머신 코드로 컴파일하므로 실행 전에 코드를 컴파일하기 위해 Lambda 런타임의 .NET 런타임이나 SDK에 의존하지 않습니다.
AOT의 한 가지 제한 사항은 .NET 8 런타임이 사용하는 것과 동일한 Amazon Linux 2023(AL2023) 운영 체제가 있는 환경에서 애플리케이션 코드를 컴파일해야 한다는 것입니다. .NET Lambda CLI는 AL2023 이미지를 사용하여 Docker 컨테이너에서 애플리케이션을 컴파일하는 기능을 제공합니다.
크로스 아키텍처 호환성과 관련된 잠재적인 문제를 방지하려면 함수에 대해 구성한 것과 동일한 프로세서 아키텍처를 사용하는 환경에서 코드를 컴파일하는 것이 좋습니다. 크로스 아키텍처 컴파일의 제한 사항에 대해 자세히 알아보려면 Microsoft .NET 설명서의 교차 컴파일
사전 조건
- Docker
-
네이티브 AOT를 사용하려면 .NET 8 런타임과 동일한 AL2023 운영 체제가 있는 환경에서 함수 코드를 컴파일해야 합니다. 다음 섹션의 .NET CLI 명령은 도커를 사용하여 AL2023 환경에서 Lambda 함수를 개발하고 빌드합니다.
- .NET 8 SDK
-
네이티브 AOT 컴파일은 .NET 8의 기능입니다. 빌드 머신에 런타임뿐만 아니라 .NET 8 SDK
도 설치해야 합니다. - Amazon.Lambda.Tools
-
Lambda 함수를 생성하려면 Amazon.Lambda.Tools
.NET 글로벌 도구 확장 을 사용합니다. Amazon.Lambda.Tools를 설치하려면 다음 명령을 실행합니다. dotnet tool install -g Amazon.Lambda.Tools
Amazon.Lambda.Tools .NET CLI 확장에 대한 자세한 내용은 GitHub에서 AWS Extensions for .NET CLI
리포지토리를 참조하세요. - Amazon.Lambda.Templates
-
Lambda 함수 코드를 생성하려면 Amazon.Lambda.Templates
NuGet 패키지를 사용합니다. 이 템플릿 패키지를 설치하려면 다음 명령을 실행합니다. dotnet new install Amazon.Lambda.Templates
시작하기
.NET 글로벌 CLI와 AWS Serverless Application Model(AWS SAM) 모두 네이티브 AOT를 사용하여 애플리케이션을 빌드하기 위한 시작 템플릿을 제공합니다. 첫 번째 네이티브 AOT Lambda 함수를 빌드하려면 다음 지침의 단계를 수행하십시오.
네이티브 AOT 컴파일된 Lambda 함수를 초기화하고 배포하기
-
네이티브 AOT 템플릿을 사용하여 새 프로젝트를 초기화한 다음 생성된
.cs
및.csproj
파일이 포함된 디렉토리로 이동합니다. 이 예제에서는 함수NativeAotSample
의 이름을 지정합니다.dotnet new lambda.NativeAOT -n NativeAotSample cd ./NativeAotSample/src/NativeAotSample
네이티브 AOT 템플릿으로 생성한
Function.cs
파일에는 다음 함수 코드가 포함되어 있습니다.using Amazon.Lambda.Core; using Amazon.Lambda.RuntimeSupport; using Amazon.Lambda.Serialization.SystemTextJson; using System.Text.Json.Serialization; namespace NativeAotSample; public class Function { /// <summary> /// The main entry point for the Lambda function. The main function is called once during the Lambda init phase. It /// initializes the .NET Lambda runtime client passing in the function handler to invoke for each Lambda event and /// the JSON serializer to use for converting Lambda JSON format to the .NET types. /// </summary> private static async Task Main() { Func<string, ILambdaContext, string> handler = FunctionHandler; await LambdaBootstrapBuilder.Create(handler, new SourceGeneratorLambdaJsonSerializer<LambdaFunctionJsonSerializerContext>()) .Build() .RunAsync(); } /// <summary> /// A simple function that takes a string and does a ToUpper. /// /// To use this handler to respond to an AWS event, reference the appropriate package from /// https://github.com/aws/aws-lambda-dotnet#events /// and change the string input parameter to the desired event type. When the event type /// is changed, the handler type registered in the main method needs to be updated and the LambdaFunctionJsonSerializerContext /// defined below will need the JsonSerializable updated. If the return type and event type are different then the /// LambdaFunctionJsonSerializerContext must have two JsonSerializable attributes, one for each type. /// // When using Native AOT extra testing with the deployed Lambda functions is required to ensure // the libraries used in the Lambda function work correctly with Native AOT. If a runtime // error occurs about missing types or methods the most likely solution will be to remove references to trim-unsafe // code or configure trimming options. This sample defaults to partial TrimMode because currently the AWS // SDK for .NET does not support trimming. This will result in a larger executable size, and still does not // guarantee runtime trimming errors won't be hit. /// </summary> /// <param name="input"></param> /// <param name="context"></param> /// <returns></returns> public static string FunctionHandler(string input, ILambdaContext context) { return input.ToUpper(); } } /// <summary> /// This class is used to register the input event and return type for the FunctionHandler method with the System.Text.Json source generator. /// There must be a JsonSerializable attribute for each type used as the input and return type or a runtime error will occur /// from the JSON serializer unable to find the serialization information for unknown types. /// </summary> [JsonSerializable(typeof(string))] public partial class LambdaFunctionJsonSerializerContext : JsonSerializerContext { // By using this partial class derived from JsonSerializerContext, we can generate reflection free JSON Serializer code at compile time // which can deserialize our class and properties. However, we must attribute this class to tell it what types to generate serialization code for. // See https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-source-generation
네이티브 AOT는 애플리케이션을 단일 네이티브 바이너리로 컴파일합니다. 해당 바이너리의 엔트리포인트는
static Main
메서드입니다.static Main
내에서 Lambda 런타임이 부트스트랩되고FunctionHandler
메서드가 설정됩니다. 런타임 부트스트랩의 일부로 소스 생성 시리얼라이저는new SourceGeneratorLambdaJsonSerializer<LambdaFunctionJsonSerializerContext>()
을(를) 사용하여 구성됩니다 -
Lambda에 애플리케이션을 배포하려면 도커가 로컬 환경에서 실행되고 있는지 확인하고 다음 명령을 실행하십시오.
dotnet lambda deploy-function
.NET 글로벌 CLI는 백그라운드에서 AL2023 도커 이미지를 다운로드하고 실행 중인 컨테이너 내에서 애플리케이션 코드를 컴파일합니다. 컴파일된 바이너리는 Lambda에 배포되기 전에 로컬 파일 시스템으로 다시 출력됩니다.
-
다음 명령을 실행하여 함수를 테스트하십시오.
<FUNCTION_NAME>
을(를) 배포 마법사에서 함수에 선택한 이름으로 바꾸십시오.dotnet lambda invoke-function <FUNCTION_NAME> --payload "hello world"
CLI의 응답에는 콜드 시작(초기화 기간)에 대한 성과 세부 정보와 함수 간접 호출의 총 실행 시간이 포함됩니다.
-
이전 단계에 따라 생성한 AWS 리소스를 삭제하려면 다음 명령을 실행하십시오.
<FUNCTION_NAME>
을(를) 배포 마법사에서 함수에 선택한 이름으로 바꾸십시오. 더 이상 사용하지 않는 AWS 리소스를 삭제하면 AWS 계정에 불필요한 요금이 청구되는 것을 방지할 수 있습니다.dotnet lambda delete-function <FUNCTION_NAME>
직렬화
네이티브 AOT를 사용하여 Lambda에 함수를 배포하려면 함수 코드가 소스 생성 직렬화Product
유형을 반환하는 Lambda 함수에는 다음과 같이 정의된 시리얼라이저가 포함됩니다.
[JsonSerializable(typeof(APIGatewayProxyRequest))] [JsonSerializable(typeof(APIGatewayProxyResponse))] [JsonSerializable(typeof(Product))] public partial class CustomSerializer : JsonSerializerContext { }
트리밍
네이티브 AOT는 컴파일 과정에서 애플리케이션 코드를 트리밍하여 바이너리가 최대한 작아지도록 합니다. .NET 8 for Lambda는 이전 버전의 .NET에 비해 향상된 트리밍 지원을 제공합니다. Lambda 런타임 라이브러리
이러한 개선 사항을 통해 빌드 시간 트리밍 경고를 제거할 수 있지만 .NET이 트림으로부터 완전히 안전하다고 할 수는 없습니다. 즉, 함수가 사용되는 라이브러리의 일부는 일부 컴파일 단계에서 제거될 수도 있습니다. 다음 예제와 같이 TrimmerRootAssemblies
를 .csproj
파일의 일부로 정의하여 이를 관리할 수 있습니다.
<ItemGroup> <TrimmerRootAssembly Include="AWSSDK.Core" /> <TrimmerRootAssembly Include="AWSXRayRecorder.Core" /> <TrimmerRootAssembly Include="AWSXRayRecorder.Handlers.AwsSdk" /> <TrimmerRootAssembly Include="Amazon.Lambda.APIGatewayEvents" /> <TrimmerRootAssembly Include="bootstrap" /> <TrimmerRootAssembly Include="Shared" /> </ItemGroup>
트리밍 경고를 받은 경우 TrimmerRootAssembly
에 경고를 생성하는 클래스를 추가해도 문제가 해결되지 않을 수 있습니다. 트리밍 경고는 클래스가 런타임까지 확인할 수 없는 다른 클래스에 액세스하려고 함을 나타냅니다. 런타임 오류를 방지하려면 TrimmerRootAssembly
에 이 두 번째 클래스를 추가합니다.
트리밍 경고 관리에 대해 자세히 알아보려면 Microsoft .NET 설명서의 트리밍 경고 소개
문제 해결
- 오류: OS 간 네이티브 컴파일은 지원되지 않습니다.
-
Amazon.Lambda.Tools .NET Core 글로벌 도구 버전이 오래되었습니다. 최신 버전으로 업데이트한 후 다시 시도하세요.
- 도커: 이 플랫폼에서는 이미지 운영 체제 ‘linux’를 사용할 수 없습니다.
-
시스템의 도커는 Windows 컨테이너를 사용하도록 구성되어 있습니다. 네이티브 AOT 빌드 환경을 실행하려면 Linux 컨테이너로 전환하세요.
일반적인 오류에 대한 자세한 내용은 GitHub에서 AWS NativeAOT for .NET