Olá! Bem-vindo a mais uma lição.
Na lição anterior, você viu como obter flexibilidade máxima ao orquestrar suas dependências, aprendendo a instruir o Aspire a construir contêineres a partir de Dockerfiles locais com o método WithDockerfile. Isso permitiu personalizar componentes do Aspire e integrar serviços que não existem como imagens prontas.
Agora que você sabe como compor uma aplicação distribuída complexa, surge uma questão fundamental para sistemas robustos: como sabemos se todos esses serviços estão realmente funcionando corretamente? Em um ambiente de microsserviços, um serviço pode estar "vivo" (o processo está rodando), mas incapaz de funcionar por que sua base de dados está offline.
Nesta lição, vamos explorar como o .NET Aspire aborda este desafio. O nosso objetivo de aprendizagem é: Descrever como o Aspire registra automaticamente as verificações de saúde (health checks) para componentes integrados. Você descobrirá o mecanismo que torna as aplicações Aspire "production-ready" por padrão, oferecendo visibilidade sobre o estado de cada parte do seu sistema.
A Importância dos Health Checks em Sistemas Distribuídos
Antes de mergulharmos no "como" do Aspire, é crucial entender o "porquê". Em sua experiência com engenharia de redes de telecomunicações, você sabe que o monitoramento constante do estado dos nós da rede é vital para a sua estabilidade. Health checks são o análogo no mundo do desenvolvimento de software para esses "pings" de monitoramento.
Um orquestrador de contêineres como Kubernetes ou mesmo o AppHost do Aspire precisa responder a duas perguntas simples sobre cada serviço:
- Liveness (Vivacidade): O serviço está rodando ou travou? Se um serviço falhar neste teste, o orquestrador deve reiniciá-lo.
- Readiness (Prontidão): O serviço está pronto para receber tráfego? Ele pode estar vivo, mas ainda inicializando ou aguardando uma dependência (como uma base de dados) ficar disponível. Se não estiver pronto, o orquestrador ou o load balancer não deve enviar novas requisições para ele.
Para entender melhor estes conceitos e sua importância, assista à seguinte seção de um vídeo.
.NET Aspire Tutorial For Beginners
O vídeo a seguir, do canal de Julio Casal, oferece uma excelente explicação conceitual sobre o que são health checks e por que eles são cruciais em ambientes de nuvem, influenciando as decisões de orquestradores de contêineres.
Assista ao trecho de 00:46:12 a 00:49:22. Foque em entender a diferença entre um contêiner não responsivo e um contêiner que não está pronto para receber tráfego devido a uma dependência falha.
O Mecanismo Automático do Aspire: ServiceDefaults
A magia da automação de health checks no Aspire reside em um projeto especial adicionado à sua solução: o YourAppName.ServiceDefaults. Este projeto contém configurações opinativas e reutilizáveis para telemetria, resiliência e, o mais importante para nós agora, health checks.
Quando você adiciona um projeto de serviço (como uma Web API) à orquestração do Aspire, duas linhas de código são tipicamente adicionadas ao seu arquivo Program.cs:
// 1. Adiciona os serviços padrão do Aspire (incluindo health checks)
builder.AddServiceDefaults();
var app = builder.Build();
// ...
// 2. Mapeia os endpoints padrão (incluindo /health e /alive)
app.MapDefaultEndpoints();
app.Run();
Vamos dissecar o que acontece por baixo dos panos.
A documentação oficial do Aspire sobre "Service Defaults" detalha exatamente o que esses métodos de extensão fazem. Esta leitura é fundamental para entender o mecanismo de automação.
Leia as seções "Explore the service defaults project", "Provided extension methods", "Add service defaults functionality" e "Health checks configuration". Preste atenção em como o método AddServiceDefaults chama internamente o AddDefaultHealthChecks, e o que este último faz.
Resumindo os pontos chave da leitura:
- O projeto
ServiceDefaultscontém métodos de extensão para configurar padrões comuns em aplicações cloud-native. - O método
builder.AddServiceDefaults()é um agregador que, entre outras coisas, chamabuilder.AddDefaultHealthChecks(). - O método
AddDefaultHealthChecks()utiliza o sistema de health checks nativo do ASP.NET Core (services.AddHealthChecks()) para registrar o serviço de verificação e adiciona um "auto-cheque" básico para garantir que a aplicação em si está responsiva. - O método
app.MapDefaultEndpoints()expõe os resultados dessas verificações através de dois endpoints HTTP:/health(Readiness): RetornaHealthysomente se a aplicação E todas as suas dependências verificadas estiverem saudáveis./alive(Liveness): RetornaHealthyse a própria aplicação estiver rodando, independentemente do estado de suas dependências.
A Mágica da Integração de Componentes
Até agora, vimos como o Aspire configura um endpoint de health check básico. A verdadeira automação acontece quando você adiciona um componente Aspire.
Quando você escreve builder.AddPostgres("db") no seu AppHost, o pacote NuGet Aspire.Npgsql faz mais do que apenas configurar a connection string. Ele também contém uma lógica que adiciona automaticamente um health check específico para PostgreSQL ao IHealthChecksBuilder da sua aplicação.
Este health check específico sabe como:
- Tentar estabelecer uma conexão com a base de dados.
- Executar uma consulta simples (ex:
SELECT 1) para verificar se a base de dados está funcional.
Isso se aplica a outros componentes também:
Aspire.StackExchange.Redisadiciona um check para o Redis.Aspire.RabbitMQ.Clientadiciona um check para o RabbitMQ.
Portanto, o resultado final do endpoint /health é um relatório agregado do "auto-cheque" da aplicação mais os resultados dos health checks de todos os componentes Aspire que você integrou.
A documentação do Aspire confirma este comportamento.
A página de documentação sobre Health Checks descreve explicitamente como as integrações adicionam suas próprias verificações.
Leia a seção "Integration health checks". Ela confirma que os pacotes de integração, como o do PostgreSQL, registram automaticamente health checks que contribuem para o status dos endpoints /health e /alive.
Vendo em Ação
Teoria é bom, mas ver o comportamento em tempo real é ainda melhor. O próximo vídeo demonstra exatamente este cenário: adicionar ServiceDefaults, parar uma dependência (PostgreSQL) e observar como o status de saúde da API é imediatamente afetado no Aspire Dashboard e no endpoint /health.
.NET Aspire Tutorial For Beginners
Vamos voltar ao tutorial de Julio Casal. Esta seção mostra passo a passo como adicionar o projeto ServiceDefaults, como o status de saúde é refletido no Dashboard e como consultar os endpoints /health e /alive para obter o status da aplicação e suas dependências.
Assista atentamente ao trecho de 00:49:22 a 00:58:49. Observe as seguintes etapas: 1) Adicionar o projeto ServiceDefaults. 2) Referenciá-lo e chamar AddServiceDefaults() e MapDefaultEndpoints() na API. 3) Adicionar .WithHttpHealthCheck() no AppHost para que o orquestrador monitore o serviço. 4) Parar o contêiner do PostgreSQL e ver a API se tornar 'Unhealthy'. 5) Testar os endpoints /alive e /health para ver as diferentes respostas.
Como visto no vídeo, quando a base de dados é parada, a API continua "viva" (endpoint /alive retorna 200 OK), mas não está "pronta" (endpoint /health retorna 503 Service Unavailable). O Aspire Dashboard reflete isso visualmente, mudando o status do serviço da API para Unhealthy. Essa é a automação em ação, fornecendo feedback instantâneo sobre a saúde do seu sistema distribuído.
Teste seu entendimento!
Imagine que você adicionou um serviço Redis à sua aplicação com builder.AddRedis("cache"). Se o contêiner do Redis falhar em iniciar, o que você esperaria que acontecesse com os endpoints /alive e /health da sua API (que usa o Redis), assumindo que os ServiceDefaults estão configurados?
Show answer
- O endpoint
/alivecontinuaria a retornar um statusHealthy(código 200), porque a sua API em si ainda está rodando. - O endpoint
/healthretornaria um statusUnhealthy(código 503), porque o health check de integração doAspire.StackExchange.Redisfalharia ao tentar se conectar ao servidor Redis.
Conclusão
Nesta lição, você desvendou como o .NET Aspire automatiza a configuração de health checks, um pilar para a construção de aplicações distribuídas observáveis e resilientes.
Principais Pontos:
- Health Checks são essenciais: Eles informam os orquestradores sobre a vivacidade (liveness) e a prontidão (readiness) dos serviços.
- Automação via
ServiceDefaults: O projetoYourAppName.ServiceDefaultse os métodos de extensãoAddServiceDefaults()eMapDefaultEndpoints()configuram a base dos health checks no ASP.NET Core. - Integração de Componentes é a Chave: Os pacotes de componentes do Aspire (ex:
Aspire.Npgsql,Aspire.StackExchange.Redis) são responsáveis por registrar automaticamente health checks específicos para a tecnologia que integram. - Visibilidade Agregada: O endpoint
/healthexpõe um status de saúde consolidado, refletindo o estado da aplicação e de todas as suas dependências monitoradas, o que é visualizado em tempo real no Aspire Dashboard.
Com esse conhecimento, você agora entende como o Aspire ajuda a garantir que seus serviços não apenas rodem, mas que estejam funcionais e prontos para o trabalho.
Próxima lição:
Agora que sabemos como um serviço pode comunicar seu estado de saúde, o próximo passo é entender como os serviços se encontram em um ambiente distribuído. Na próxima lição, iniciaremos um novo módulo sobre comunicação e resiliência, começando com Service Discovery, o mecanismo que o Aspire usa para permitir que os serviços se comuniquem uns com os outros de forma transparente, sem a necessidade de hard-coding de endereços e portas.