Compartilhar via


padrões do serviço .NET.NET Aspire

Neste artigo, você aprenderá sobre o projeto padrão do serviço .NET.NET Aspire, um conjunto de métodos de extensão que:

  • Conecte de telemetria, de verificações de integridade, de descoberta de serviço ao seu aplicativo.
  • São personalizáveis e extensíveis.

Os aplicativos nativos de nuvem geralmente exigem configurações abrangentes para garantir que funcionem em diferentes ambientes de forma confiável e segura. .NET Aspire fornece muitos métodos auxiliares e ferramentas para simplificar o gerenciamento de configurações para OpenTelemetry, verificações de integridade, variáveis de ambiente e muito mais.

Explorar o projeto de padrões de serviço

Quando você Inscrever-se em .NET.NET Aspire de orquestração ou criar um novo projeto .NET.NET Aspire, o projeto YourAppName.ServiceDefaults.csproj é adicionado à sua solução. Por exemplo, ao criar uma API, você chama o método AddServiceDefaults no arquivo Program.cs de seus aplicativos:

builder.AddServiceDefaults();

O método AddServiceDefaults manipula as seguintes tarefas:

  • Configura OpenTelemetry métricas e rastreamento.
  • Adiciona pontos de extremidade de verificação de integridade padrão.
  • Adiciona a funcionalidade de descoberta de serviço.
  • Configura HttpClient para trabalhar com a descoberta de serviço.

Para obter mais informações, consulte Métodos de extensão fornecidos para obter detalhes sobre o método AddServiceDefaults.

Importante

O projeto padrão do serviço .NET.NET Aspire foi projetado especificamente para compartilhar o arquivo Extensions.cs e sua funcionalidade. Não inclua outras funcionalidades ou modelos compartilhados neste projeto. Use um projeto convencional de biblioteca de classes compartilhadas para essas finalidades.

Características do projeto

O projeto YourAppName.ServiceDefaults é uma biblioteca 9.0 que contém o seguinte XML:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <IsAspireSharedProject>true</IsAspireSharedProject>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />

    <PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="9.0.0" />
    <PackageReference Include="Microsoft.Extensions.ServiceDiscovery" Version="9.0.0" />
    <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.10.0" />
    <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.10.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.10.1" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.10.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.10.0" />
  </ItemGroup>

</Project>

O modelo de projeto padrão do serviço impõe uma dependência FrameworkReference em Microsoft.AspNetCore.App.

Ponta

Se você não quiser usar uma dependência do Microsoft.AspNetCore.App, poderá criar um projeto padrão de serviço personalizado. Para obter mais informações, consulte padrões de serviço personalizado.

A propriedade IsAspireSharedProject é definida como true, o que indica que este projeto é um projeto compartilhado. A ferramenta .NET Aspire usa esse projeto como referência para outros projetos adicionados a uma solução .NET Aspire. Ao inscrever o novo projeto para orquestração, ele faz referência automaticamente ao projeto YourAppName.ServiceDefaults e atualiza o arquivo Program.cs para chamar o método AddServiceDefaults.

Métodos de extensão fornecidos

O projeto YourAppName.ServiceDefaults expõe um único arquivo Extensions.cs que contém vários métodos de extensão opinativos:

  • AddServiceDefaults: adiciona a funcionalidade padrão do serviço.
  • ConfigureOpenTelemetry: configura OpenTelemetry métricas e rastreamento.
  • AddDefaultHealthChecks: adiciona pontos de extremidade de verificação de integridade padrão.
  • MapDefaultEndpoints: mapeia o ponto de extremidade de verificação de integridade para /health e o ponto de extremidade de vida para /alive.

Adicionar funcionalidade de padrões de serviço

O método AddServiceDefaults define as configurações padrão com a seguinte funcionalidade opinativa:

public static IHostApplicationBuilder AddServiceDefaults(
    this IHostApplicationBuilder builder)
{
    builder.ConfigureOpenTelemetry();

    builder.AddDefaultHealthChecks();

    builder.Services.AddServiceDiscovery();

    builder.Services.ConfigureHttpClientDefaults(http =>
    {
        // Turn on resilience by default
        http.AddStandardResilienceHandler();

        // Turn on service discovery by default
        http.AddServiceDiscovery();
    });

    // Uncomment the following to restrict the allowed schemes for service discovery.
    // builder.Services.Configure<ServiceDiscoveryOptions>(options =>
    // {
    //     options.AllowedSchemes = ["https"];
    // });

    return builder;
}

O código anterior:

  • Configura OpenTelemetry métricas e rastreamento chamando o método ConfigureOpenTelemetry.
  • Adiciona pontos de extremidade de verificação de integridade padrão chamando o método AddDefaultHealthChecks.
  • Adiciona funcionalidade de de descoberta de serviço chamando o método AddServiceDiscovery.
  • Configura HttpClient padrões chamando o método ConfigureHttpClientDefaults, que se baseia em criar aplicativos HTTP resilientes: padrões de desenvolvimento chave:
    • Adiciona o manipulador de resiliência HTTP padrão chamando o método AddStandardResilienceHandler.
    • Especifica que o IHttpClientBuilder deve usar a descoberta de serviço chamando o método UseServiceDiscovery.
  • Retorna a instância IHostApplicationBuilder para permitir o encadeamento de métodos.

configuração de OpenTelemetry

A telemetria é uma parte crítica de qualquer aplicativo nativo de nuvem. .NET Aspire fornece um conjunto de padrões opinativos para OpenTelemetry, que são configurados com o método ConfigureOpenTelemetry:

public static IHostApplicationBuilder ConfigureOpenTelemetry(
    this IHostApplicationBuilder builder)
{
    builder.Logging.AddOpenTelemetry(logging =>
    {
        logging.IncludeFormattedMessage = true;
        logging.IncludeScopes = true;
    });

    builder.Services.AddOpenTelemetry()
        .WithMetrics(metrics =>
        {
            metrics.AddAspNetCoreInstrumentation()
                .AddHttpClientInstrumentation()
                .AddRuntimeInstrumentation();
        })
        .WithTracing(tracing =>
        {
            if (builder.Environment.IsDevelopment())
            {
                // We want to view all traces in development
                tracing.SetSampler(new AlwaysOnSampler());
            }

            tracing.AddAspNetCoreInstrumentation()
                // Uncomment the following line to enable gRPC instrumentation 
                // (requires the OpenTelemetry.Instrumentation.GrpcNetClient package)
                //.AddGrpcClientInstrumentation()
                .AddHttpClientInstrumentation();
        });

    builder.AddOpenTelemetryExporters();

    return builder;
}

O método ConfigureOpenTelemetry:

  • Adiciona .NET.NET Aspire registro em log telemetria para incluir mensagens formatadas e escopos.
  • Adiciona OpenTelemetry métricas e rastreamento que incluem:
    • Métricas de instrumentação de runtime.
    • ASP.NET Core métricas de instrumentação.
    • Métricas de instrumentação httpClient.
    • Em um ambiente de desenvolvimento, o AlwaysOnSampler é usado para exibir todos os rastreamentos.
    • Detalhes de rastreamento para ASP.NET Core, gRPC e instrumentação HTTP.
  • Adiciona OpenTelemetry exportadores, chamando AddOpenTelemetryExporters.

O método AddOpenTelemetryExporters é definido em particular da seguinte maneira:

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.AspNetCore package)
    //if (!string.IsNullOrEmpty(
    //    builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
    //{
    //    builder.Services.AddOpenTelemetry()
    //       .UseAzureMonitor();
    //}

    return builder;
}

O método AddOpenTelemetryExporters adiciona exportadores OpenTelemetry com base nas seguintes condições:

  • Se a variável de ambiente OTEL_EXPORTER_OTLP_ENDPOINT estiver definida, o exportador de OpenTelemetry será adicionado.
  • Opcionalmente, os consumidores de .NET Aspire padrões de serviço podem descompactar algum código para habilitar o exportador do Prometheus ou o exportador do Azure Monitor.

Para obter mais informações, consulte .NET.NET Aspirede telemetria.

Configuração de verificações de integridade

As verificações de integridade são usadas por várias ferramentas e sistemas para avaliar a preparação do seu aplicativo. .NET .NET Aspire fornece um conjunto de padrões opinativos para verificações de integridade, que são configurados com o método AddDefaultHealthChecks:

public static IHostApplicationBuilder AddDefaultHealthChecks(
    this IHostApplicationBuilder builder)
{
    builder.Services.AddHealthChecks()
        // Add a default liveness check to ensure app is responsive
        .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);

    return builder;
}

O método AddDefaultHealthChecks adiciona uma verificação de vida padrão para garantir que o aplicativo seja responsivo. A chamada para AddHealthChecks registra o HealthCheckService. Para obter mais informações, consulte .NET.NET Aspire verificações de integridade.

Configuração de verificações de integridade do aplicativo Web

Para expor verificações de integridade em um aplicativo Web, .NET.NET Aspire determina automaticamente o tipo de projeto que está sendo referenciado dentro da solução e adiciona a chamada apropriada para MapDefaultEndpoints:

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();

    // Adding health checks endpoints to applications in non-development 
    // environments has security implications.
    // See https://aka.ms/dotnet/aspire/healthchecks for details before 
    // enabling these endpoints in non-development environments.
    if (app.Environment.IsDevelopment())
    {
        // 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;
}

O método MapDefaultEndpoints:

  • Permite que os consumidores descompactem opcionalmente algum código para habilitar o ponto de extremidade prometheus.
  • Mapeia o ponto de extremidade de verificações de integridade para /health.
  • Mapeia o ponto de extremidade de vida para /alive rota em que a marca de verificação de integridade contém live.

Para obter mais informações, consulte .NET.NET Aspire verificações de integridade.

Padrões de serviço personalizado

Se a configuração de serviço padrão fornecida pelo modelo de projeto não for suficiente para suas necessidades, você terá a opção de criar seu próprio projeto padrão de serviço. Isso é especialmente útil quando seu projeto de consumo, como um projeto worker ou winforms, não pode ou não deseja ter uma dependência FrameworkReference em Microsoft.AspNetCore.App.

Para fazer isso, crie um novo projeto de biblioteca de classes do .NET 9.0 e adicione as dependências necessárias ao arquivo de projeto, considere o seguinte exemplo:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Library</OutputType>
    <TargetFramework>net9.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" />
    <PackageReference Include="Microsoft.Extensions.ServiceDiscovery" />
    <PackageReference Include="Microsoft.Extensions.Http.Resilience" />
    <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" />
    <PackageReference Include="OpenTelemetry.Extensions.Hosting" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Http" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Runtime" />
  </ItemGroup>
</Project>

Em seguida, crie uma classe de extensões que contenha os métodos necessários para configurar os padrões do aplicativo:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;

namespace Microsoft.Extensions.Hosting;

public static class AppDefaultsExtensions
{
    public static IHostApplicationBuilder AddAppDefaults(
        this IHostApplicationBuilder builder)
    {
        builder.ConfigureAppOpenTelemetry();

        builder.Services.AddServiceDiscovery();

        builder.Services.ConfigureHttpClientDefaults(http =>
        {
            // Turn on resilience by default
            http.AddStandardResilienceHandler();

            // Turn on service discovery by default
            http.AddServiceDiscovery();
        });

        return builder;
    }

    public static IHostApplicationBuilder ConfigureAppOpenTelemetry(
        this IHostApplicationBuilder builder)
    {
        builder.Logging.AddOpenTelemetry(logging =>
        {
            logging.IncludeFormattedMessage = true;
            logging.IncludeScopes = true;
        });

        builder.Services.AddOpenTelemetry()
            .WithMetrics(static metrics =>
            {
                metrics.AddRuntimeInstrumentation();
            })
            .WithTracing(tracing =>
            {
                if (builder.Environment.IsDevelopment())
                {
                    // We want to view all traces in development
                    tracing.SetSampler(new AlwaysOnSampler());
                }

                tracing.AddGrpcClientInstrumentation()
                       .AddHttpClientInstrumentation();
            });

        builder.AddOpenTelemetryExporters();

        return builder;
    }

    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());
        }

        return builder;
    }
}

Este é apenas um exemplo e você pode personalizar a classe AppDefaultsExtensions para atender às suas necessidades específicas.

Próximas etapas

Esse código é derivado do modelo de aplicativo .NET.NET Aspire Starter e destina-se como um ponto de partida. Você é livre para modificar esse código, no entanto, você considera necessário atender às suas necessidades. É importante saber que o projeto padrão do serviço e sua funcionalidade são aplicados automaticamente a todos os recursos do projeto em uma solução .NET.NET Aspire.