本文翻译自 James Montemagno 的 .NET Aspire Quick Tip – Managing Container & Data Lifetime
.NET Aspire 凭借其强大的应用程序组合编排功能增强了本地开发流程。在 .NET Aspire 应用程序主机中,您可以在一个集中位置为应用程序指定所有项目、可执行文件、云资源和容器。当您运行应用程序主机项目时,.NET Aspire 将自动运行您的项目和可执行文件,根据需要配置云资源,并下载和运行应用程序依赖的容器。.NET Aspire 9 添加了新功能,让您可以更好地控制在本地计算机上管理容器生命周期的方式,从而在使用容器时加快开发速度。
.NET Aspire 容器
让我们看一个简单的 .NET Aspire 应用程序主机示例,该示例创建一个本地 Redis 容器资源,等待其可用后,为 Web 项目配置连接字符串:
// Create a distributed application builder given the command line arguments.
var builder = DistributedApplication.CreateBuilder(args);
// Add a Redis server to the application.
var cache = builder.AddRedis("cache");
// Add the frontend project to the application and configure it to use the
// Redis server, defined as a referenced dependency.
builder.AddProject<Projects.MyFrontend>("frontend")
.WithReference(cache)
.WaitFor(cache);
当 App Host 启动后,对 AddRedis
的调用将下载相应的 Redis 镜像。
它还会创建一个新的 Redis 容器并自动运行它。
当我们停止调试 App Host 时,.NET Aspire 会自动停止所有项目,同时停止 Redis 容器并删除通常用于存储数据的关联卷。
容器生命周期
虽然上述方式适用于许多场景,但如果容器没有任何更改,您可能会希望容器始终保持运行,而不受 App Host 状态的影响。这时就轮到新的 WithLifetime
API 出场,它允许您自定义容器的生命周期。这意味着您可以将容器配置为启动并保持运行状态,从而加快项目启动速度,因为容器随时可用,并且可以重复使用数据卷。
var builder = DistributedApplication.CreateBuilder(args);
// Add a Redis server to the application and set lifetime to persistent
var cache = builder.AddRedis("cache")
.WithLifetime(ContainerLifetime.Persistent);
builder.AddProject<Projects.MyFrontend>("frontend")
.WithReference(cache)
.WaitFor(cache);
现在,当我们运行App Host时,如果未找到容器,它会创建一个新的容器资源并启动它,但是,如果找到了指定名称的容器资源,.NET Aspire 会使用该资源而不是创建一个新的资源。当 App Host 关闭时,容器资源不会被终止,从而允许您在多次运行中重复使用它!您可以在 .NET Aspire 仪表板上看到一个小图钉图标,表示该容器已设置为持久化
状态。
它是如何工作的?
默认情况下,当设置了 ContainerLifetime.Persistent
时,.NET Aspire 会考虑多种因素以确定是使用现有容器还是创建新容器。.NET Aspire 首先根据 App Host 项目路径的哈希值为容器生成唯一名称。这意味着此容器只对于特定的 App Host 项目是持久的,如果您有多个 App Host 项目,并不会全局生效。您可以使用 WithContainerName
方法给容器指定一个名称,这样可以创建一个全局唯一的持久化容器。
除了容器名称之外,.NET Aspire 还会考虑以下因素:
- 容器镜像
- 启动容器的命令及其参数
- 数据卷挂载
- 公开的容器端口
- 环境变量
- 容器重启策略
.NET Aspire 会获取所有这些信息并从中创建一个唯一的哈希值,以便与任何现有的容器数据进行比较。如果这些设置中有任何不同,则不会重复使用现有容器,而是将创建一个新容器。因此,如果你好奇为什么会创建新容器,那可能是因为某些配置发生了变化。这是 .NET Aspire 在一开始针对此新选项采用的非常严格的策略,团队正在寻求有关未来迭代的反馈。
持久化数据
现在,我们在 App Host 的多次启动之间实现了容器的持久化,这也意味着我们正在重用与其关联的数据卷。数据卷是保存容器生成的数据的推荐方法,其优点是可以同时存储来自多个容器的数据,提供高性能,并且易于备份或迁移。因此,尽管我们确实在重复使用数据卷,但如果设置发生了更改,仍然可能会创建一个新容器。通过对使用和重复使用的数据卷进行更精准的控制,我们可以实现以下功能:
- 在应用程序启动期间维护 Redis 实例中的缓存数据或消息。
- 在延长的开发会话期间处理数据库中的连续数据集。
- 在 Azure Blob 存储模拟器中测试或调试不断变化的文件集。
因此,我们用 WithDataVolume
方法告诉容器资源要使用哪个数据卷。默认情况下,它将根据我们的项目和资源名称分配一个名称:{appHostProjectName}-{resourceName}-data
,但我们也可以定义将要创建和重用的名称,这在我们有多个 App Host 时很有帮助。
var cache = builder.AddRedis("cache")
.WithLifetime(ContainerLifetime.Persistent)
.WithDataVolume("myredisdata");
现在,将为该容器资源创建一个新的并重复使用的数据卷,并且如果由于某种原因创建了新容器,它仍将使用 myredisdata
卷。
使用数据卷是一个很好的选择,因为它们提供了理想的性能、可移植性和安全性。然而,有时您可能需要直接访问和修改计算机上的文件。当您需要实时更改时,就可以使用数据绑定挂载。
var cache = builder.AddRedis("cache")
.WithLifetime(ContainerLifetime.Persistent)
.WithDataBindMount(@"C:\Redis\Data");
数据绑定挂载依赖于文件系统以确保容器重启后保留 Redis 数据。在这里,数据绑定挂载会在 Windows 上挂载到 Redis 容器中的 C:\Redis\Data
路径。
对于 Redis,我们还可以控制数据持久化的方式,例如在特定时间间隔和阈值时对数据进行快照保存。
var cache = builder.AddRedis("cache")
.WithLifetime(ContainerLifetime.Persistent)
.WithDataVolume("myredisdata")
.WithPersistence(interval: TimeSpan.FromMinutes(5), keysChangedThreshold: 100);
在这里,interval
表示快照导出之间的时间间隔,keysChangedThreshold
表示触发快照所需的键更改操作次数。
不同的集成对 WithDataVolume
和 WithBindMount
有各自的规范,因此请务必查阅您所使用的集成的文档。
更好地控制资源
现在,我们已在 App Host 中完成了所有设置、持久化并准备就绪。额外的好消息是,.NET Aspire 9 中还新增了直接从仪表板启动、停止和重启资源(包括容器)的功能!
这项功能非常棒,可以让您在不离开仪表板的情况下测试应用程序的弹性。
升级到 .NET Aspire 9
在 .NET Aspire 9 中还有更多功能,因此请务必阅读.NET Aspire 9.0 中的新增功能文档,并通过完整的升级指南在几分钟内轻松完成升级。
此外,还更新了有关容器资源生命周期、使用数据卷持久化数据和新仪表板功能的文档。
欢迎在下方评论中告诉我们您对 .NET Aspire 9 中这项新功能以及其他所有出色功能的看法。
0 comments
Be the first to start the discussion.