简介
在几天前的.NET 8发布会上,来自微软的Glenn Condron和David Fowler为我们演示了.NET Aspire,在Visual Studio的帮助下,它展现出了惊人的开发效率。
短短的十分钟内,David现场演示了如何轻松创建了一个具有服务发现,健康检查,故障和容错策略,Redis服务,可观测性以及遥测面板的云原生应用,而且它还表现出来了强大的可扩展性。
开发者可以使用它快速创建一个属于自己的云原生应用,或者将已有的项目改造成云原生应用。
背景
一直以来,.NET开发者都凭借微软提供的ASP.NET Core框架和丰富的核心类库,来构建各种软件系统。随着云原生概念的出现,我们发现要实现云原生应用开发并不是一帆风顺的事情。
这需要我们深入了解更多的组件,重新审视服务编排和系统架构。而且为了赋予云原生应用更强大的能力,我们不得不在成百上千的Github项目中寻找或重构所需的类库,并且每个人都必须学习和正确配置使用它们。
这就像在搭积木,但问题是我们得到的积木并非成套,甚至我们一开始并不知道手里的积木会拼成什么样,我们需要从海量的积木仓库中拼凑出一套完整的产品出来。
优势
.NET Aspire是一个独立的云原生应用开发框架。云原生应用通常由多种中间组件,资源和微服务组成,.NET Aspire提供了一些解决特定云原生问题的能力:
编排: 提供高级抽象的能力,简化了云原生应用中不同服务的配置和连接,管理服务发现、环境变量和容器配置。
组件: 提供NuGet包,包含常用服务(如日志,服务发现,重试熔断策略,可观测性, Redis,Postgres,RabbitMQ, Azure等),通过标准化接口确保每个应用连接一致。
工具: 提供Visual Studio和dotnet CLI 项目模板和工具,快速创建和运行.NET Aspire应用。
官网在描述.NET Aspire时使用了 "opinionated" 一词,该词直译过来是“固执己见的”或“有主见的”,其实它的含义是相对于基础且灵活的ASP.NET Core框架,.NET Aspire的项目格式更加统一和固定。
总之,.NET Aspire简化了云原生应用内各元素的协调和管理。
开发者无需处理底层实现细节,而是将服务之间的复杂关系交给Aspire来处理。
核心概念
资源
在.NET Aspire,.NET服务,容器或者可执行文件都被看作是资源。下面是一段简单的示例代码:
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddRedisContainer("cache");
var apiservice = builder.AddProject<Projects.AspireApp_ApiService>("apiservice");
builder.AddProject<Projects.AspireApp_Web>("webfrontend")
.WithReference(cache)
.WithReference(apiservice);
builder.Build().Run();
Aspire Host 正在编排服务之间的关系,首先是声明了一个Redis容器,然后是注册API服务,之后又注册了由Blazor创建的UI服务,同时声明了UI服务对Redis和Api服务的引用。
在项目启动后,UI服务中的HttpClient可以直接使用服务名称调用相应的服务。
组件
.NET Aspire提供了一系列精心挑选的NuGet包,专门用于促进云原生应用与目前流行的服务和平台的集成。每个组件通过自动配置或标准化的配置模式提供了基本的云原生功能。
目前可用于使用的.NET Aspire组件:
- PostgreSQL,PostgreSQL Entity Framework Core
- SQL Server,SQL Server Entity Framework Core
- RabbitMQ,Azure Service Bus
- Redis,Redis Distributed Caching,Redis Output Caching
- Azure Blob Storage,Azure Cosmos DB Entity Framework Core,Azure Cosmos DB, Azure Key Vault,Azure Storage Queues,Azure Table Storage
这些组件简化了健康检查、可观察性、遥测和弹性配置。.NET Aspire的依赖注入、云原生特性和组件配置方式统一,旨在减轻云原生应用程序的开发和管理负担。
云原生特性
可观察性
NET Aspire为我们集成了OpenTelemetry SDK,以收集运行时各项数据指标。例如将遥测数据导出到指定服务:
private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder)
{
var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);
if (useOtlpExporter)
{
builder.Services.Configure<OpenTelemetryLoggerOptions>(logging => logging.AddOtlpExporter());
builder.Services.ConfigureOpenTelemetryMeterProvider(metrics => metrics.AddOtlpExporter());
builder.Services.ConfigureOpenTelemetryTracerProvider(tracing => tracing.AddOtlpExporter());
}
// Uncomment the following lines to enable the Prometheus exporter (requires the OpenTelemetry.Exporter.Prometheus.AspNetCore package)
// builder.Services.AddOpenTelemetry()
// .WithMetrics(metrics => metrics.AddPrometheusExporter());
// Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.Exporter package)
// builder.Services.AddOpenTelemetry()
// .UseAzureMonitor();
return builder;
}
采集需要的应用指标数据:
public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder)
{
builder.Logging.AddOpenTelemetry(logging =>
{
logging.IncludeFormattedMessage = true;
logging.IncludeScopes = true;
});
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics =>
{
metrics.AddRuntimeInstrumentation()
.AddBuiltInMeters();
})
.WithTracing(tracing =>
{
if (builder.Environment.IsDevelopment())
{
// We want to view all traces in development
tracing.SetSampler(new AlwaysOnSampler());
}
tracing.AddAspNetCoreInstrumentation()
.AddGrpcClientInstrumentation()
.AddHttpClientInstrumentation();
});
builder.AddOpenTelemetryExporters();
return builder;
}
private static MeterProviderBuilder AddBuiltInMeters(this MeterProviderBuilder meterProviderBuilder) =>
meterProviderBuilder.AddMeter(
"Microsoft.AspNetCore.Hosting",
"Microsoft.AspNetCore.Server.Kestrel",
"System.Net.Http");
健康检查
.NET Aspire会为每个组件添加健康检查端点
public static WebApplication MapDefaultEndpoints(this WebApplication app)
{
// Uncomment the following line to enable the Prometheus endpoint (requires the OpenTelemetry.Exporter.Prometheus.AspNetCore package)
// app.MapPrometheusScrapingEndpoint();
// All health checks must pass for app to be considered ready to accept traffic after starting
app.MapHealthChecks("/health");
// Only health checks tagged with the "live" tag must pass for app to be considered alive
app.MapHealthChecks("/alive", new HealthCheckOptions
{
Predicate = r => r.Tags.Contains("live")
});
return app;
}
故障恢复
使用著名的Polly类库,默认实现重试,超时等策略。
builder.Services.ConfigureHttpClientDefaults(http =>
{
// Turn on resilience by default
http.AddStandardResilienceHandler();
// Turn on service discovery by default
http.UseServiceDiscovery();
});
仪表板
.NET Aspire 项目模板提供了一个复杂的仪表板,用于全面的应用监视和检查。通过此仪表板,我们可以在本地开发时实时查看应用程序的各个方面,包括日志、遥测数据和环境配置等,提供对应用状态和结构的深刻概述。
我们可以看到Aspire所管理的一切资源,服务,容器,可执行文件,日志等。下面放一些图片大家可以自行感受。
总结
.NET Aspire 应用程序采用与云无关的原则构建,允许在支持 .NET 和容器的各种平台上灵活部署。Aspire还会为应用生成资源清单文件,在目前的pr1版本中,可以直接在Azure上进行容器部署,并且未来会有更多环境得到支持。
好了,对.NET Aspire简单介绍就到这里,如果感兴趣的话就按照官网文档创建项目体验一下吧!
Introducing .NET Aspire: Simplifying Cloud-Native Development with .NET 8 - .NET Blog (microsoft.com)
.NET Aspire overview - .NET Aspire | Microsoft Learn
aspire/README.md at main · dotnet/aspire · GitHub