Lambda 托管实例的 .NET 运行时 - Amazon Lambda
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

Lambda 托管实例的 .NET 运行时

对于 .NET 运行时,Lambda 托管实例在每个执行环境中使用单个 .NET 进程。使用 .NET 任务处理多个并发请求。

并发配置

Lambda 向每个执行环境发送的最大并发请求数由函数配置中的 PerExecutionEnvironmentMaxConcurrency 设置控制。这是一项可选设置,其默认值因运行时而异。对于 .NET 运行时而言,其默认设置为每个 vCPU 32 个并发请求,或者您也可以自行配置其他数值。Lambda 会根据每个执行环境吸收这些请求的容量,自动调整并发请求的数量,最高到配置的最大值。

为多并发构建函数

在使用 Lambda 托管实例时,您应像在任何其他多并发环境中一样,采用相同的并发安全措施。由于处理程序对象在所有任务中是共享的,因此任何可变状态都必须是线程安全的。这包括集合、数据库连接以及在请求处理过程中被修改的任何静态对象。

Amazon SDK 客户端是线程安全的,且不需要特殊处理。

示例:数据库连接池

以下代码使用静态的数据库连接对象,该对象在并发请求之间共享。SqlConnection 对象不是线程安全的。

public class DBQueryHandler { // Single connection shared across threads - NOT SAFE private SqlConnection connection; public DBQueryHandler() { connection = new SqlConnection("your-connection-string-here"); connection.Open(); } public string Handle(object input, ILambdaContext context) { using var cmd = connection.CreateCommand(); cmd.CommandText = "SELECT ..."; // your query using var reader = cmd.ExecuteReader(); ... } }

要解决这个问题,请为每个请求使用从连接池中获取的单独连接。打开连接对象时,Microsoft.Data.SqlClient 之类的 ADO.NET 提供程序会自动支持连接池。

public class DBQueryHandler { public DBQueryHandler() { } public string Handle(object input, ILambdaContext context) { using var connection = new SqlConnection("your-connection-string-here"); connection.Open(); using var cmd = connection.CreateCommand(); cmd.CommandText = "SELECT ..."; // your query using var reader = cmd.ExecuteReader(); ... } }

示例:集合

标准的 .NET 集合不是线程安全的:

public class Handler { private static List<string> items = new List<string>(); private static Dictionary<string, object> cache = new Dictionary<string, object>(); public string FunctionHandler(object input, ILambdaContext context) { items.Add(context.AwsRequestId); cache["key"] = input; return "Success"; } }

使用 System.Collections.Concurrent 命名空间中的集合以确保并发安全:

public class Handler { private static ConcurrentBag<string> items = new ConcurrentBag<string>(); private static ConcurrentDictionary<string, object> cache = new ConcurrentDictionary<string, object>(); public string FunctionHandler(object input, ILambdaContext context) { items.Add(context.AwsRequestId); cache["key"] = input; return "Success"; } }

共享的 /tmp 目录

/tmp 目录在执行环境中为所有并发请求共享使用。对同一个文件进行并发写入可能会导致数据损坏,例如,如果另一个请求覆盖了该文件。要解决这个问题,要么为共享文件实施文件锁定机制,要么根据每次请求使用唯一的文件名以避免冲突。记得清理不再需要的文件,以免耗尽可用空间。

日志记录

在多并发系统中,日志交错(即来自不同请求的日志条目在日志中交错排列)是常见现象。使用 Lambda 托管实例的函数始终使用高级日志记录控制引入的结构化 JSON 日志格式。此格式包括 requestId,使得日志条目能够与单个请求相关联。当您使用 context.Logger 对象生成日志时,requestId 会自动包含在每个日志条目中。有关更多信息,请参阅将 Lambda 高级日志记录控制与 .NET 结合使用

请求上下文

使用 context.AwsRequestId 属性访问当前请求的请求 ID。

使用 context.TraceId 属性访问 X-Ray 跟踪 ID。这为当前请求的跟踪 ID 提供了并发安全的访问权限。Lambda 不支持将 _X_AMZN_TRACE_ID 环境变量用于 Lambda 托管实例。使用 Amazon SDK 时,X-Ray 跟踪 ID 会自动传播。

初始化和关闭

函数初始化会在每个执行环境中发生一次。初始化期间创建的对象在请求之间共享。

对于带有扩展程序的 Lambda 函数,其执行环境在关闭时会发出一个 SIGTERM 信号。扩展程序使用此信号来触发清理任务,例如刷新缓冲区。您可以订阅 SIGTERM 事件来触发函数清理任务,例如关闭数据库连接。要了解有关执行环境生命周期的更多信息,请参阅了解 Lambda 执行环境生命周期

依赖项版本

Lambda 托管实例需要以下最低程序包版本:

  • Amazon.Lambda.Core:版本 2.7.1 或更高版本

  • Amazon.Lambda.RuntimeSupport:版本 1.14.1 或更高版本

  • OpenTelemetry.Instrumentation.AWSLambda:版本 1.14.0 或更高版本

  • AWSXRayRecorder.Core:版本 2.16.0 或更高版本

  • AWSSDK.Core:版本 4.0.0.32 或更高版本

Powertools for Amazon Lambda (.NET)

适用于 Amazon Lambda (.NET) 的 Powertools适用于 OpenTelemetry 的 Amazon Distro - 适用于 .Net 的检测工具目前不支持 Lambda 托管实例。

后续步骤