mcpField
D
dotnet-aspire

dotnet-aspire

github.com/markpitt开发24103 次安装36 周前更新
代码仓库

关于 dotnet-aspire

.NET Aspire Integration Skill 提供在现有 .NET 解决方案中加入 .NET Aspire,或创建 Aspire 分布式应用的模块化指南,涵盖服务编排、发现、配置、可观测性、资源集成和部署。

主要功能

  1. 01AppHost 与 ServiceDefaults 配置指南
  2. 02服务编排与发现模式
  3. 03配置及机密管理指南
  4. 04可观测性与本地仪表板设置
  5. 05资源集成与部署指南

适用场景

  1. 01为多服务 .NET 解决方案添加 Aspire
  2. 02创建启用 Aspire 的分布式应用
  3. 03设置本地服务编排
  4. 04准备云部署配置

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/markpitt/claude-skills --skill dotnet-aspire

安装后在 Claude Code 中输入/dotnet-aspire确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

resources/
components.md
configuration-management.md
deployment.md
local-development.md
service-communication.md

详细介绍

.NET Aspire 集成技能

此技能可帮助你将 .NET Aspire 添加到现有的 .NET 解决方案中,或创建启用了 Aspire 的新分布式应用程序。它提供有关编排、服务发现、组件集成、配置管理和部署的模块化指导。

什么是 .NET Aspire?

.NET Aspire 是一个具有明确主张、适用于云环境的技术栈,用于构建可观测、可用于生产环境的分布式应用程序。它提供:

  • 服务编排 - 通过依赖项管理协调多个项目和服务
  • 服务发现 - 自动发现服务并建立服务间连接
  • 遥测与可观测性 - 内置日志记录、指标和分布式跟踪
  • 配置管理 - 集中式配置,支持强类型和机密信息
  • 资源预配 - 与数据库、缓存、消息传递和云服务集成
  • 开发者仪表板 - 本地监控和调试界面

何时使用此技能

在以下情况下使用此技能:

  • 将 Aspire 添加到包含多个服务的现有 .NET 解决方案中
  • 使用 Aspire 创建新的分布式应用程序
  • 使微服务或分布式系统现代化,以便部署到云端
  • 为本地开发和部署设置服务编排
  • 集成云原生可观测性和配置模式

我需要什么组件/功能?

需求资源说明
整体结构概述与设置从分析到运行的分步实施指南
数据库、缓存、消息传递resources/components.md所有可用的 Aspire 组件包及示例
服务间通信resources/service-communication.md服务发现、HttpClient 模式、弹性
配置与机密信息resources/configuration-management.md环境设置、机密信息、功能标志
本地开发resources/local-development.md仪表板、调试、测试、运行状况检查
生产部署resources/deployment.mdAzure Container Apps、Kubernetes、Docker Compose

概述与设置

核心概念

.NET Aspire 使用两个关键项目:

  • AppHost - 编排服务和资源;提供开发者仪表板
  • ServiceDefaults - 所有服务的共享配置(OpenTelemetry、运行状况检查、服务发现)
先决条件
# Install .NET Aspire workload
dotnet workload install aspire

# Verify installation
dotnet workload list  # Should show "aspire"

# Docker Desktop (for container resources)
# Ensure it's running before launching AppHost
基本实施流程

1. 分析解决方案

  • 确定服务(API、Web 应用、工作进程)
  • 列出外部依赖项(数据库、Redis、消息队列)
  • 确定服务通信模式

2. 创建 Aspire 项目

dotnet new aspire-apphost -n MyApp.AppHost
dotnet new aspire-servicedefaults -n MyApp.ServiceDefaults
dotnet sln add MyApp.AppHost/MyApp.AppHost.csproj
dotnet sln add MyApp.ServiceDefaults/MyApp.ServiceDefaults.csproj

3. 配置服务

  • 为每个服务添加 ServiceDefaults 引用
  • 在 Program.cs 中调用 builder.AddServiceDefaults()
  • 对 ASP.NET Core 服务调用 app.MapDefaultEndpoints()

4. 在 AppHost 中编排

var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddRedis("cache");
var database = builder.AddPostgres("postgres").AddDatabase("appdb");

var api = builder.AddProject<Projects.MyApi>("api")
    .WithReference(database)
    .WithReference(cache);

var web = builder.AddProject<Projects.MyWeb>("web")
    .WithReference(api)
    .WithExternalHttpEndpoints();

builder.Build().Run();

5. 更新服务通信

  • 将硬编码 URL 替换为服务名称
  • 使用与 builder.AddServiceDefaults() 匹配的模式

6. 运行并验证

dotnet run --project MyApp.AppHost
# Opens dashboard at https://localhost:15001

关键决策

AppHost 项目命名:

  • 约定:[SolutionName].AppHost
  • 示例:对于名为 "ECommerceSystem" 的解决方案,创建 "ECommerceSystem.AppHost"

服务资源名称:

  • 在 AppHost 中使用简短、描述性强的名称
  • 示例:"api"、"web"、"worker"、"cache"、"database"
  • 这些名称用于服务发现 URL

资源管理:

  • 本地开发:使用 Aspire 管理的容器(PostgreSQL、Redis、RabbitMQ)
  • 生产环境:由 azd 自动预配 Azure 资源,或手动配置
  • 连接字符串:自动注入;通常无需硬编码

服务发现设置:

  • HttpClient URL 使用服务名称:使用 http://api,而非 https://localhost:7001
  • Aspire 负责处理服务间的路由和身份验证
  • 外部服务使用显式端点配置

常见架构

Web API + 前端
var api = builder.AddProject<Projects.Api>("api")
    .WithReference(database)
    .WithExternalHttpEndpoints();

var web = builder.AddProject<Projects.Web>("web")
    .WithReference(api)
    .WithExternalHttpEndpoints();
使用消息队列的微服务
var messaging = builder.AddRabbitMQ("messaging");

var orderService = builder.AddProject<Projects.OrderService>("orders")
    .WithReference(messaging);

var inventoryService = builder.AddProject<Projects.InventoryService>("inventory")
    .WithReference(messaging);
多数据库系统
var postgres = builder.AddPostgres("postgres")
    .AddDatabase("users")
    .AddDatabase("products");

var mongo = builder.AddMongoDB("mongo")
    .AddDatabase("orders");

var userApi = builder.AddProject<Projects.UserApi>("userapi")
    .WithReference(postgres);

var orderApi = builder.AddProject<Projects.OrderApi>("orderapi")
    .WithReference(mongo);

资源索引

如需详细的实现指导,请参阅:

  • 组件 - 组件包和集成模式:resources/components.md
  • 服务通信 - 服务发现和服务间调用:resources/service-communication.md
  • 配置管理 - 密钥、环境变量、设置:resources/configuration-management.md
  • 本地开发 - 控制面板功能、调试、运行状况检查:resources/local-development.md
  • 部署 - Azure Container Apps、Kubernetes、Docker Compose:resources/deployment.md

最佳实践

服务组织
  • 让 AppHost 专注于组合,而非业务逻辑
  • 使用 ServiceDefaults 处理跨领域关注点(可观测性、运行状况检查)
  • 确保每个服务都能使用回退配置独立运行
资源管理
  • 使用 Aspire 管理的资源,确保本地开发的一致性
  • 在 AppHost 中通过 .WithReference() 明确声明依赖项
  • 为数据库添加数据持久化:.WithDataVolume()
配置模式
  • 开发环境:使用 appsettings.Development.json 和 .WithEnvironment()
  • 生产环境:使用 Azure Key Vault 或托管密钥
  • 避免将密钥提交到源代码管理;在本地使用用户机密
可观测服务
  • 通过 ServiceDefaults 启用 OpenTelemetry(自动)
  • 使用开发者控制面板进行本地调试
  • 在生产环境中将遥测数据导出到 Application Insights 或类似服务

常见问题与解决方案

服务无法通信

  • 确认 AppHost 中的服务名称与 HttpClient URL 一致
  • 确保所有服务都调用了 AddServiceDefaults()
  • 检查 ASP.NET 服务是否调用了 MapDefaultEndpoints()

未注入连接字符串

  • 使用 builder.AddNpgsqlDbContext<>(),而非手动配置
  • 确认 AppHost 和服务中的数据库/资源名称一致
  • 确认项目文件中存在 ServiceDefaults 引用

控制面板无法启动

  • 确保 Docker Desktop 正在运行
  • 检查端口冲突(默认端口:15001)
  • 确认运行的是 AppHost 项目,而非单个服务

运行状况检查失败

  • 在控制面板中查看资源启动日志
  • 检查本地计算机上的端口是否可用
  • 确认 Docker 有足够的资源

入门检查清单

  • 安装 .NET Aspire 工作负载并验证
  • 分析解决方案结构并识别服务
  • 创建 AppHost 和 ServiceDefaults 项目
  • 为每个服务添加 ServiceDefaults 引用
  • 使用 AddServiceDefaults() 和 MapDefaultEndpoints() 更新服务的 Program.cs
  • 配置 AppHost 编排服务和资源
  • 更新服务的 HttpClient URL,以使用服务发现名称
  • 使用 dotnet run --project AppHost 在本地测试
  • 确认控制面板显示所有服务均在运行
  • 配置部署目标(Azure、Kubernetes 等)

后续步骤

  1. 了解组件详情 → 请参阅 resources/components.md
  2. 了解服务通信 → 请参阅 resources/service-communication.md
  3. 了解配置 → 请参阅 resources/configuration-management.md
  4. 了解本地开发 → 请参阅 resources/local-development.md
  5. 了解部署 → 请参阅 resources/deployment.md

请记住:从单个服务开始,确认通信正常后,再逐步增加复杂性。在部署到生产环境之前,先使用控制面板在本地调试问题。

  1. 哪些项目应编排为服务?
  2. 需要哪些外部资源(数据库、Redis、存储等)?
  3. 应采用最精简的 Aspire 设置,还是包含其他组件?
  4. 是否已有 Docker 或编排配置?
2. 澄清问题

实施前,请与用户确认:

服务识别:

  • “我已在您的解决方案中识别出 [X] 个服务:[list]。这些服务是否都应纳入 Aspire 编排?”
  • “是否还应添加其他服务或项目?”

基础设施要求:

  • “我看到有对 [database/Redis/etc.] 的引用。是否应由 Aspire 管理这些资源?”
  • “您想使用容器资源还是连接字符串配置?”

Aspire 结构:

  • “是否应创建一个名为 ‘[SolutionName].AppHost’ 的新 AppHost 项目,以及一个名为 ‘[SolutionName].ServiceDefaults’ 的 ServiceDefaults 项目?”
  • “您是否偏好特定的命名约定?”

依赖关系:

  • “哪些服务相互依赖?(这有助于设置服务发现)”
  • “是否有任何启动顺序要求?”
3. 实施步骤
步骤 1:创建 Aspire 项目

创建 AppHost 项目:

dotnet new aspire-apphost -n [SolutionName].AppHost

AppHost 项目:

  • 编排所有服务和资源
  • 定义服务依赖项和配置
  • 提供用于本地开发的开发者仪表板
  • 包含用于组合应用程序的 Program.cs

创建 ServiceDefaults 项目:

dotnet new aspire-servicedefaults -n [SolutionName].ServiceDefaults

ServiceDefaults 项目:

  • 提供共享的服务配置
  • 配置 OpenTelemetry、运行状况检查和服务发现
  • 应用于所有服务,以确保行为一致

将项目添加到解决方案:

dotnet sln add [SolutionName].AppHost/[SolutionName].AppHost.csproj
dotnet sln add [SolutionName].ServiceDefaults/[SolutionName].ServiceDefaults.csproj
步骤 2:配置服务项目

对于每个服务项目(API、Web 应用、Worker):

  1. 添加 ServiceDefaults 引用:
dotnet add [ServiceProject] reference [SolutionName].ServiceDefaults/[SolutionName].ServiceDefaults.csproj
  1. 更新 Program.cs 以注册服务默认值:
// At the top of Program.cs, after builder creation
var builder = WebApplication.CreateBuilder(args);

// Add this line
builder.AddServiceDefaults();

// ... rest of service configuration ...

var app = builder.Build();

// Add this line before app.Run()
app.MapDefaultEndpoints();

app.Run();
  1. 对于 Worker 服务,模式类似:
var builder = Host.CreateApplicationBuilder(args);

builder.AddServiceDefaults();

// ... service configuration ...

var host = builder.Build();
host.Run();
步骤 3:配置 AppHost

在 AppHost 中添加项目引用:

dotnet add [SolutionName].AppHost reference [ServiceProject1]/[ServiceProject1].csproj
dotnet add [SolutionName].AppHost reference [ServiceProject2]/[ServiceProject2].csproj

更新 AppHost Program.cs 以编排服务:

var builder = DistributedApplication.CreateBuilder(args);

// Add infrastructure resources
var cache = builder.AddRedis("cache");
var postgres = builder.AddPostgres("postgres")
    .AddDatabase("appdb");

// Add services with dependencies
var apiService = builder.AddProject<Projects.MyApi>("apiservice")
    .WithReference(postgres)
    .WithReference(cache);

var webApp = builder.AddProject<Projects.MyWebApp>("webapp")
    .WithReference(apiService)
    .WithExternalHttpEndpoints();

builder.Build().Run();

常见资源方法:

  • .AddRedis("name") - Redis 缓存
  • .AddPostgres("name").AddDatabase("dbname") - PostgreSQL
  • .AddSqlServer("name").AddDatabase("dbname") - SQL Server
  • .AddRabbitMQ("name") - RabbitMQ 消息传递
  • .AddMongoDB("name").AddDatabase("dbname") - MongoDB
  • .AddAzureStorage("name") - Azure Storage

服务配置方法:

  • .WithReference(resource) - 添加依赖项并注入连接信息
  • .WithExternalHttpEndpoints() - 使服务可从外部访问
  • .WithReplicas(count) - 运行多个实例
  • .WithEnvironment("KEY", "value") - 添加环境变量
  • .WithHttpsEndpoint(port: 7001) - 指定 HTTPS 端口
步骤 4:添加所需的 NuGet 包

Aspire 包由模板自动添加,但请确认以下内容:

AppHost 项目:

  • Aspire.Hosting.AppHost(通常通过 workload 引入)
  • 资源所需的其他托管包(例如 Aspire.Hosting.PostgreSQL)

ServiceDefaults 项目:

  • Microsoft.Extensions.Http.Resilience
  • Microsoft.Extensions.ServiceDiscovery
  • OpenTelemetry.Exporter.OpenTelemetryProtocol
  • OpenTelemetry.Extensions.Hosting
  • OpenTelemetry.Instrumentation.AspNetCore
  • OpenTelemetry.Instrumentation.Http
  • OpenTelemetry.Instrumentation.Runtime

服务项目:

  • Aspire.Npgsql.EntityFrameworkCore.PostgreSQL(如果使用 PostgreSQL)
  • Aspire.StackExchange.Redis(如果使用 Redis)
  • 数据库、消息传递等所需的组件包

安装包:

dotnet add [Project] package [PackageName]
步骤 5:更新服务间通信

对于调用其他服务的服务,请使用服务发现:

之前(硬编码 URL):

builder.Services.AddHttpClient("apiservice", client =>
{
    client.BaseAddress = new Uri("https://localhost:7001");
});

之后(服务发现):

builder.Services.AddHttpClient("apiservice", client =>
{
    client.BaseAddress = new Uri("http://apiservice");
});

服务名称需与 AppHost 的 AddProject<>() 调用中的名称一致。

对于强类型 HttpClient:

builder.Services.AddHttpClient<IApiClient, ApiClient>(client =>
{
    client.BaseAddress = new Uri("http://apiservice");
});
步骤 6:配置和连接字符串

资源连接字符串会自动注入。更新服务配置:

之前:

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));

之后:

builder.AddNpgsqlDbContext<AppDbContext>("appdb");

连接名称(“appdb”)与 AppHost 中的数据库名称一致。

对于 Redis:

builder.AddRedisClient("cache");
步骤 7:验证和测试

运行 AppHost 项目:

dotnet run --project [SolutionName].AppHost

这将启动:

  • Aspire 仪表板(通常位于 https://localhost:15001)
  • 所有已配置的服务
  • 所有资源容器(Redis、PostgreSQL 等)

验证:

  1. 仪表板显示所有服务均在运行
  2. 服务可通过服务发现进行通信
  3. 仪表板中显示遥测数据
  4. 资源连接正常工作
4. 高级配置
外部服务

对于不在解决方案中的服务:

var externalApi = builder.AddProject<Projects.ExternalApi>("external-api")
    .WithHttpsEndpoint(port: 8001);
容器资源

在容器中运行服务:

var myApi = builder.AddContainer("myapi", "myapiimage")
    .WithHttpEndpoint(port: 8000, targetPort: 80);
Azure 资源

对于托管在 Azure 上的资源:

var storage = builder.AddAzureStorage("storage")
    .AddBlobs("blobs");

var keyVault = builder.AddAzureKeyVault("keyvault");
自定义资源

使用自定义资源扩展 Aspire:

var customResource = builder.AddResource(new CustomResource("name"))
    .WithEndpoint("http", endpoint => endpoint.Port = 9000);

最佳实践

1. 服务组织
  • 让 AppHost 专注于编排,而非业务逻辑
  • 使用 ServiceDefaults 处理横切关注点
  • 确保每项服务都能独立运行(并提供回退配置)
2. 资源管理
  • 在本地开发中使用 Aspire 托管的资源
  • 在生产部署中使用连接字符串
  • 为数据库配置资源持久化(避免数据丢失)
3. 配置
  • 使用 appsettings.Development.json 设置本地覆盖项
  • 将敏感数据保存在用户机密或密钥保管库中
  • 使用特定于环境的配置
4. 依赖项
  • 在 AppHost 中显式定义服务依赖项
  • 使用 .WithReference() 注入连接信息
  • 考虑数据库迁移的启动顺序
5. 可观测性
  • 利用内置的 OpenTelemetry 进行分布式追踪
  • 使用仪表板进行本地调试
  • 为每项服务配置适当的日志级别

常见模式

API 网关模式
var apiGateway = builder.AddProject<Projects.ApiGateway>("gateway")
    .WithExternalHttpEndpoints();

var serviceA = builder.AddProject<Projects.ServiceA>("servicea");
var serviceB = builder.AddProject<Projects.ServiceB>("serviceb");

apiGateway.WithReference(serviceA).WithReference(serviceB);
带消息队列的工作进程
var messaging = builder.AddRabbitMQ("messaging");

var worker = builder.AddProject<Projects.Worker>("worker")
    .WithReference(messaging);

var api = builder.AddProject<Projects.Api>("api")
    .WithReference(messaging);
带后端 API 的 Web 应用
var cache = builder.AddRedis("cache");
var database = builder.AddPostgres("postgres").AddDatabase("appdb");

var api = builder.AddProject<Projects.Api>("api")
    .WithReference(database)
    .WithReference(cache);

var web = builder.AddProject<Projects.Web>("web")
    .WithReference(api)
    .WithExternalHttpEndpoints();

故障排除

服务发现无法正常工作
  • 确保在服务的 Program.cs 中调用 builder.AddServiceDefaults()
  • 确认 HttpClient 中的服务名称与 AppHost 的 AddProject 名称一致
  • 检查是否为 ASP.NET 服务调用了 app.MapDefaultEndpoints()
未注入连接字符串
  • 确认 AppHost 和服务配置中的资源名称一致
  • 使用 builder.AddNpgsqlDbContext<>(),而非手动调用 AddDbContext
  • 确认存在 ServiceDefaults 引用
无法访问仪表板
  • 检查 AppHost 是否正在运行(而非单独的服务)
  • 确认端口未被阻止(默认值:15001)
  • 在 AppHost 控制台输出中查找仪表板 URL
资源无法启动
  • 确保 Docker Desktop 正在运行(适用于容器资源)
  • 检查端口是否与现有服务冲突
  • 查看 AppHost 控制台中的启动错误

要修改的文件

将 Aspire 添加到现有解决方案时,预计需要修改:

  1. 解决方案文件 (.sln) - 添加 AppHost 和 ServiceDefaults 项目
  2. 每项服务的 Program.cs - 添加服务默认值注册
  3. 每项服务的 .csproj - 添加 ServiceDefaults 引用
  4. AppHost/Program.cs - 定义编排和资源
  5. 服务配置 - 将硬编码的 URL 替换为服务发现
  6. 数据库配置 - 使用 Aspire 组件方法

先决条件

确保已安装以下内容:

  • .NET 8.0 SDK 或更高版本
  • .NET Aspire 工作负载:dotnet workload install aspire
  • Docker Desktop(适用于容器资源)

验证安装:

dotnet workload list

输出中应显示已安装的工作负载包含“aspire”。

摘要检查清单

实现 Aspire 后,请验证:

  • 已创建 AppHost 项目并将其添加到解决方案
  • 已创建 ServiceDefaults 项目并将其添加到解决方案
  • 所有服务项目都引用了 ServiceDefaults
  • 服务的 Program.cs 文件调用了 AddServiceDefaults() 和 MapDefaultEndpoints()
  • AppHost Program.cs 使用恰当的依赖关系编排所有服务
  • 服务间通信使用服务发现(而非硬编码 URL)
  • 数据库和缓存连接使用 Aspire 组件方法
  • AppHost 成功运行并启动仪表板
  • 所有服务均显示在仪表板中,且状态健康
  • 显示了跨服务请求的遥测数据

其他资源

有关特定组件和模式的详细信息,请参阅:

  • resources/components.md - Aspire 组件包和配置
  • resources/deployment.md - 将 Aspire 应用部署到生产环境

示例输出

完成后,解决方案结构应如下所示:

MySolution/
├── MySolution.sln
├── MySolution.AppHost/
│   ├── Program.cs                 # Orchestration configuration
│   ├── MySolution.AppHost.csproj
│   └── appsettings.json
├── MySolution.ServiceDefaults/
│   ├── Extensions.cs              # Service defaults implementation
│   └── MySolution.ServiceDefaults.csproj
├── MySolution.Api/
│   ├── Program.cs                 # Calls AddServiceDefaults()
│   └── MySolution.Api.csproj      # References ServiceDefaults
├── MySolution.Web/
│   ├── Program.cs                 # Calls AddServiceDefaults()
│   └── MySolution.Web.csproj      # References ServiceDefaults
└── MySolution.Worker/
    ├── Program.cs                 # Calls AddServiceDefaults()
    └── MySolution.Worker.csproj   # References ServiceDefaults

运行 dotnet run --project MySolution.AppHost 会启动所有服务,并打开仪表板以监控和调试分布式应用程序。

评论

支持 Markdown