使用 .NET Aspire 构建和调试 .NET Lambda 应用程序(第 2 部分)
在我们关于 .NET Aspire 和 Amazon Lambda 的博客文章的第 1 部分中,我们向您展示了如何使用 .NET Aspire 来运行和调试 .NET Lambda 函数。在本部分(第 2 部分)中,我们将向您展示如何利用 .NET Aspire 编程模型来实现优秀实践以及连接缓存层和数据存储库等依赖资源。我们还将向您展示如何使用 OpenTelemetry 从应用程序中获取遥测数据,这些数据可以在 .NET Aspire 仪表板中查看。
起始代码
以下代码是 .NET 开发人员为了使用缓存从数据存储中查找账户而可能编写的代码。在这种情况下,我们从资源路径中获取账户 ID,在 Redis 缓存中查找该账户,如果找不到该账户,则回退到数据存储,在本例中为 Amazon DynamoDB。当代码从数据存储中获取项目时,它会将该账户放入 Redis 缓存中以备将来提取。
出于演示目的,对逻辑进行了简化,但它显示了在运行和调试 .NET Lambda 函数时使用外部依赖关系所面临的挑战。当我们将该函数部署到 Lambda 时,该函数将使用真实的 DynamoDB 服务,并使用亚马逊 ElastiCache 预置 Redis 集群。在开发环境中运行时,我们如何连接这些依赖关系?我们不希望我们的代码根据它是在本地运行还是部署而改变。在这里,.NET Aspire 的编程模型可以改变我们构建 .NET Lambda 函数的方式。
设置 OpenTelemetry
在 .NET 项目(包括 .NET Lambda 项目)中使用 OpenTelemetry,可以让你深入了解应用程序在其组件上的运行情况。.NET Aspire 旨在简化为 .NET 应用程序启用 OpenTelemetry 的体验。
.NET Aspire 应用程序的常见模式是使用服务默认项目。该项目包含一系列扩展方法,可用于设置常用设置和优秀实践,包括在 .NET Aspire 应用程序中在 .NET 项目中启用 OpenTelemetry。要将服务默认项目添加到您的解决方案,请选择"添加-> 新建项目...",然后选择 .NET Aspire 服务默认项目模板。常见的惯例是命名服务默认项目<solution-name>.ServiceDefaults
。
要为我们的亚马逊云科技和 Redis 组件启用 OpenTelemetry 跟踪,请将以下软件包添加到服务默认项目中。
- OpenTelemetry.instrumentation.aws — 用于测试适用于 .NET 的亚马逊云科技开发工具包。
- openTelemetry.instrumentation.awsLambda — 用于检测 .NET Lambda 函数,包括为 Lambda 调用创建总体跟踪。
- openTelemetry.instrumentation.StackExchangeredis — 用于检测 Redis 的访问权限。请注意,在撰写本文时,该软件包目前被标记为预览版
1.11.0-beta.1
。
接下来,我们需要在Extensions.cs
文件中的ConfigureOpenTelemetry
方法中启用这些包。
为了让 .NET Lambda 函数使用服务默认扩展方法,它需要有关服务默认项目的项目引用,并且需要使用 IHostApplicationBuilder 构建器配置其使用的服务。在以下代码的构造函数中,使用 HostApplicationBuilder 来构造依赖注入容器,并调用AddServiceDefaults
扩展方法来添加我们的常用设置,包括我们所做的 OpenTelemetry 配置。
通过 Lambda 函数完成的所有网络操作,例如联系 DynamoDB 和 Redis,都应包含在父级 OpenTelemetry 跟踪中。这使我们能够查看在 Lambda 调用中花费的时间以及潜在的错误区域在哪里。要为 Lambda 调用创建跟踪,请使用 openTelemetry.instrumentation.awsLambda NuGet 包中的AWSLambdaWrapper.TraceAsync
方法。
对 OpenTelemetry 的 Lambda 函数所做的更改与在真实 Lambda 服务或 .NET Aspire 中运行时所需的更改相同。Lambda 函数中的任何代码都没有将其与 .NET Aspire 或本地体验联系起来。
设置开发者内部循环
在之前的博客文章中,我们向您展示了如何使用 .NET Aspire 应用程序主机来协调在本地运行的应用程序。对于我们的 Lambda 函数,我们需要使用账户表协调对 Redis 实例和 DynamoDB 的访问。对于 DynamoDB,我们可以选择在 DynamoDB 中配置账户表,也可以选择使用本地的 DynamoDB。在本演练中,我们将使用 DynamoDB 本地。
首先,将以下软件包添加到 .NET Aspire 应用程序主机中:
- Aspire.Hosting.aws
- awssdk.dynamodbv2
- Aspire.Hosting.Redis
在Program.cs
中,添加 Redis 和 DynamoDB 资源。这些扩展方法负责启动 .NET Aspire 实例的底层容器镜像。
此时我们有一个 DynamoDB 本地实例正在运行,但它没有表或数据。使用以下代码创建账户表并在表中创建账户。一旦 DynamoDB 本地容器表示其处于就绪状态,就会调用该Subscribe
方法中的代码。
运行 .NET Aspire 应用程序主机,我们可以看到我们已经成功地将 Redis 和 DynamoDB 本地添加到我们的 .NET Aspire 应用程序中。我们需要做的下一个任务是配置 Lambda 函数以使用这些资源。
在之前的博客文章中,我们讨论了使用AddAWSLambdaFunction
和AddAWSAPIGatewayEmulator
扩展方法将 .NET Lambda 函数作为资源添加到 .NET Aspire 应用程序中。回想一下,这些 API 被标记为预览版,因此要使用它们,你需要包括以下代码中显示的 #pragma。
此代码使用这些方法添加 Lambda 函数并配置通过 Amazon API Gateway 终端节点的访问。要将该函数连接到我们的 Redis 和 DynamoDB 资源,需要WithReference
使用该方法。DynamoDB 本地资源的WithReference
方法会覆盖 DynamoDB 服务客户端在 Lambda 函数中创建的终端节点。Redis 资源的WithReference
方法将连接字符串添加到 Lambda 函数中。如本博客文章前面所示,Lambda 函数中的这一builder.AddRedisClient(connectionName: "cache")
行查找连接字符串并使用它。
此时,开发人员内部循环已设置完毕,这样当我们启动应用程序主机时,Redis 容器、DynamoDB 本地和 .NET Lambda 函数都将启动并连接。以下是应用程序主机的完整代码以供参考。
在行动中
现在,.NET Aspire 应用程序主机已经设置完毕,让我们看看它的实际运行情况。在安装了 C# 开发套件的 Visual Studio 或 Visual Studio Code 中,启动应用程序宿主项目。在 .NET Aspire 仪表板中,我们可以看到所有资源都在运行。通过查看 Lambda 函数的详细信息,您可以看到为连接 Redis 容器和 DynamoDB 本地实例而设置的环境变量。
当我们通过 API 网关仿真器导航到 GET 账户 REST 端点时http://localhost:<apigateway-port>/account/1
,我们可以看到在 DynamoDB 本地播种的数据。如果我们在导航时在 Lambda 函数中设置了断点,则会兑现这些断点。
回到 .NET Aspire 仪表板,导航到"跟踪"部分,然后单击"获取账户函数:获取账户函数"追踪信息。跟踪记录显示了先前完成的 OpenTelemetry 设置收集的所有活动。
如果我们再次导航到 GET 账户终端节点,我们会看到一条新的跟踪记录,其中跳过了 DynamoDB 本地数据,因为数据已缓存在 Redis 中。
自动化测试
.NET Aspire 还可以使用 Aspire.Hosting.Testing NuGet 包进行端到端集成测试。这意味着我们可以在测试中运行 .NET Aspire 应用程序主机,包括所有资源,例如 Redis 和 DynamoDB 本地资源,作为测试的一部分。可以从应用程序主机检索资源并进行检查。
以下测试显示了如何启动应用程序主机并创建HttpClient
配置为 API Gateway 模拟器的,以便通过模拟器发出 HTTP 请求并调用 Lambda 函数。
您还可以使用适用于 .NET 的亚马逊云科技开发工具包直接通过 Lambda 模拟器调用 Lambda 函数。这对于未通过 API 网关调用的 Lambda 函数很有用。以下测试显示了如何发现 Lambda 模拟器的终端节点,然后配置 Lambda 服务客户端以调用 Lambda 函数。
请注意,将 Lambda 服务客户端配置ServiceURL
为指向 Lambda 仿真器时,Lambda 服务客户端中唯一支持的操作是调用方法。
结论
.NET Aspire 和 .NET Lambda 函数的组合允许简化本地开发人员内部循环所需资源的编排。应用程序主机设置连接,这样 .NET 开发人员就无需离开 IDE 来不断迭代代码。端到端体验可以通过 .NET Aspire 仪表板手动测试,也可以通过端到端集成测试自动测试。
此功能的开发正在我们的 aws/integrations-on-dotnet-aspire-for-aws 存储库中进行。以下 GitHub 问题被用作 Lambda 集成的主要跟踪器问题:https://github.com/aws/integrations-on-dotnet-aspire-for-aws/issues/17。我们要求正在构建 Lambda 函数的 .NET 开发人员试用此预览版,并在我们的存储库中告诉我们您的成功案例以及与 Lambda 集成相关的任何问题。
.NET