Olá! Bem-vindo de volta.
Na lição anterior, você construiu sua primeira aplicação distribuída com .NET Aspire, definindo um App Host e adicionando projetos de serviço a ele. Você deve ter notado que o template criou um projeto chamado ServiceDefaults, mas nós o deixamos de lado. Hoje, vamos colocar esse projeto sob os holofotes.
O objetivo desta lição é configurar os Service Defaults para habilitar health checks padronizados e a integração com OpenTelemetry. Entender este projeto é fundamental, pois ele é o coração da filosofia "cloud-ready" do Aspire, fornecendo resiliência e observabilidade de forma consistente a todos os seus serviços com o mínimo de esforço.
1. O que são os Service Defaults?
Em uma arquitetura de microsserviços, muitas preocupações são transversais (cross-cutting concerns): como os serviços emitem logs? Como eles expõem seu estado de saúde? Como coletamos métricas e traces? Sem uma abordagem padronizada, cada serviço pode acabar com sua própria implementação, levando a inconsistências e a uma grande quantidade de código repetitivo (boilerplate).
O projeto ServiceDefaults do Aspire resolve exatamente isso. Ele é uma biblioteca de classes compartilhada que contém um conjunto opinativo, mas customizável, de configurações para:
- Observabilidade (OpenTelemetry): Habilita logs, métricas e tracing distribuído.
- Health Checks: Expõe endpoints padronizados para que sistemas de orquestração possam monitorar a saúde do serviço.
- Resiliência (Polly): Configura políticas de retry e circuit breaker para chamadas HTTP (abordaremos em uma lição futura).
- Service Discovery: Permite que os serviços se encontrem na rede (também em uma lição futura).
Ao adicionar uma única linha, builder.AddServiceDefaults(), ao Program.cs de um serviço, você o "inscreve" nesse conjunto de convenções.
Para uma visão geral e oficial, leia a introdução da documentação do .NET Aspire sobre Service Defaults. Ela estabelece o propósito e os componentes principais que vamos explorar.
Leia as seções "Explore the service defaults project" e "Provided extension methods". Foque em entender o papel do projeto e as tarefas que o método AddServiceDefaults realiza. Isso vai nos dar a base para o resto da lição.
2. Habilitando Health Checks Padronizados
Health checks são endpoints simples que informam a um orquestrador (como o Aspire localmente, ou Kubernetes em produção) se uma aplicação está funcionando corretamente. Existem dois tipos principais:
- Liveness (
/alive): "A aplicação está rodando?". Se este endpoint falhar, significa que a aplicação travou e precisa ser reiniciada. - Readiness (
/health): "A aplicação está pronta para receber tráfego?". Este endpoint verifica não apenas se a aplicação está rodando, mas também se suas dependências (banco de dados, outros serviços) estão acessíveis. Se falhar, o orquestrador para de enviar tráfego para a instância, mas não a reinicia, dando tempo para que ela se recupere.
Como o Aspire implementa Health Checks
Vamos olhar o código. No seu projeto ServiceDefaults, abra o arquivo Extensions.cs. Você encontrará dois métodos importantes: AddDefaultHealthChecks e MapDefaultEndpoints.
-
AddDefaultHealthChecks:public static TBuilder AddDefaultHealthChecks<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder { builder.Services.AddHealthChecks() // Add a default liveness check to ensure app is responsive .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); return builder; }Este método registra o serviço de health checks do ASP.NET Core e adiciona um primeiro check chamado
"self". Note a tag["live"], que o identifica como um check de liveness. -
MapDefaultEndpoints:public static WebApplication MapDefaultEndpoints(this WebApplication app) { // ... app.MapHealthChecks("/health"); app.MapHealthChecks("/alive", new HealthCheckOptions { Predicate = r => r.Tags.Contains("live") }); // ... }Este método mapeia os endpoints HTTP.
/healthexecuta todos os health checks (readiness), enquanto/aliveexecuta apenas aqueles com a tag"live"(liveness).
O mais poderoso é que, quando você adiciona componentes Aspire (como um banco de dados ou cache), eles automaticamente adicionam seus próprios health checks, que são incluídos no endpoint /health.
Aplicação Prática
Vamos aplicar isso ao projeto MyAspireApp.ApiService que você criou na lição anterior.
- Verifique se o seu
MyAspireApp.ApiService/Program.cstem as seguintes linhas:// No topo do arquivo builder.AddServiceDefaults(); // ... antes de app.Run() app.MapDefaultEndpoints(); - Inicie a aplicação Aspire a partir do diretório do AppHost:
cd MyAspireApp.AppHost dotnet run - Quando o dashboard abrir, encontre o endpoint do seu
apiservice. Se ele estiver rodando, por exemplo, emhttps://localhost:7001, abra novas abas e navegue para:https://localhost:7001/alive-> Você verá a resposta "Healthy".https://localhost:7001/health-> Você também verá "Healthy".
No dashboard, o status do seu serviço apiservice deve aparecer como "Running".
.NET Aspire Tutorial For Beginners
O vídeo a seguir, do canal Julio Casal, demonstra de forma brilhante o poder dos health checks no Aspire. Ele para intencionalmente uma dependência (um banco de dados) e mostra como o status de saúde da API muda automaticamente.
Assista ao trecho de 46:12 a 59:14. Preste atenção especial em como o status da API no dashboard muda de 'Running' para 'Unhealthy' quando a dependência é interrompida. Isso ilustra perfeitamente o propósito do check de 'readiness'. Você verá também como os endpoints /alive e /health respondem de maneira diferente.
3. Habilitando Observabilidade com OpenTelemetry
Observabilidade é a capacidade de entender o estado interno de um sistema a partir de seus outputs externos. OpenTelemetry (OTel) é um padrão aberto para instrumentar, gerar, coletar e exportar dados de telemetria, que se baseiam em três pilares:
- Logs: Eventos discretos que aconteceram, úteis para depuração.
- Traces: Representam o fluxo de uma única requisição através de múltiplos serviços (tracing distribuído). Essencial para identificar gargalos e entender interações.
- Metrics: Medições numéricas agregadas ao longo do tempo (ex: número de requisições por segundo, uso de CPU).
A configuração manual do OpenTelemetry pode ser complexa. O Aspire Service Defaults torna isso trivial.
Como o Aspire implementa OpenTelemetry
No mesmo arquivo Extensions.cs, você encontrará o método ConfigureOpenTelemetry.
public static TBuilder ConfigureOpenTelemetry<TBuilder>(this TBuilder builder)
where TBuilder : IHostApplicationBuilder
{
builder.Logging.AddOpenTelemetry(...); // 1. Conecta os logs ao OTel
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics => ...) // 2. Configura as métricas
.WithTracing(tracing => ...); // 3. Configura os traces
builder.AddOpenTelemetryExporters(); // 4. Configura para onde enviar os dados
return builder;
}
A parte mais importante para o desenvolvimento local é o método AddOpenTelemetryExporters. Ele verifica por uma variável de ambiente, OTEL_EXPORTER_OTLP_ENDPOINT. O App Host do Aspire define automaticamente essa variável para cada serviço, apontando para um endpoint no próprio Aspire Dashboard. É assim que toda a telemetria flui para o dashboard sem nenhuma configuração manual.
Aplicação Prática: Explorando a Observabilidade
Como AddServiceDefaults já chama ConfigureOpenTelemetry, tudo está pronto.
- Com sua aplicação rodando, acesse um endpoint da sua
apiservicealgumas vezes (por exemplo,https://localhost:7001/weatherforecast). - Vá para o Aspire Dashboard e clique na linha do seu
apiservice. - Explore as abas à esquerda:
- Structured Logs: Você verá os logs da sua aplicação, não como texto puro, mas como dados estruturados. Você pode filtrar por propriedades, como
RequestId, para ver todos os logs de uma única requisição. - Traces: Aqui está a mágica do tracing distribuído. Você verá cada chamada HTTP que você fez. Ao clicar em uma, você verá uma "cascata" (waterfall) mostrando a duração de cada etapa interna da sua requisição. Se seu serviço chamasse outro, você veria essa chamada como parte da mesma trace.
- Metrics: Explore as métricas que o Aspire coleta por padrão. Você pode ver gráficos para
aspnetcore_requests_total(total de requisições) ouhttp_client_request_duration_seconds(duração de chamadas HTTP feitas pelo seu serviço).
- Structured Logs: Você verá os logs da sua aplicação, não como texto puro, mas como dados estruturados. Você pode filtrar por propriedades, como
Code to cloud with .NET Aspire - David Fowler & Damian Edwards
David Fowler e Damian Edwards, os criadores do Aspire, demonstram essa experiência 'turnkey' de observabilidade. Ver a explicação deles sobre o porquê e como isso foi construído é extremamente valioso para entender os princípios de design.
Assista ao trecho de 39:23 a 46:36. Eles adicionam o ServiceDefaults, executam a aplicação e exploram os logs estruturados e, mais importante, as traces distribuídas no dashboard. Eles explicam como isso permite uma visão profunda do que está acontecendo durante o desenvolvimento.
Teste seu entendimento!
Você está depurando um problema de performance. Uma requisição a um endpoint está demorando mais do que o esperado. Qual dos três pilares da observabilidade (Logs, Traces, Metrics) no Aspire Dashboard seria o mais útil para começar sua investigação e por quê?
Show answer
A aba Traces seria o melhor lugar para começar. Uma trace distribuída mostraria uma visualização em cascata (waterfall) de todas as operações que compõem a requisição (ex: processamento da API, chamadas a banco de dados, chamadas a outros serviços). Isso permitiria que você identificasse visualmente qual operação específica está consumindo a maior parte do tempo e, portanto, é o gargalo de performance.
Conclusão
Nesta lição, você desvendou o projeto ServiceDefaults e viu como ele é essencial para construir aplicações robustas com .NET Aspire. Com uma única linha de código, você obteve um sistema padronizado de health checks e uma infraestrutura completa de observabilidade.
Principais Pontos:
- O projeto
ServiceDefaultscentraliza configurações transversais para garantir consistência entre os serviços. - Health Checks (
/alivee/health) são cruciais para a resiliência e são habilitados pelos métodosAddDefaultHealthCheckseMapDefaultEndpoints. - OpenTelemetry fornece os três pilares da observabilidade: Logs, Traces e Métricas.
AddServiceDefaults()habilita tudo isso, e o App Host configura automaticamente os serviços para enviarem telemetria para o Aspire Dashboard, proporcionando uma experiência de desenvolvimento local rica e perspicaz.
Na próxima lição, faremos um tour mais aprofundado pelo Aspire Dashboard. Agora que você sabe como os dados chegam lá, vamos nos concentrar em como usar o dashboard de forma eficaz para monitorar, diagnosticar e depurar suas aplicações distribuídas.