Estamos na semana 43 de 2024, faltam 9 semanas para o réveillon. Desde a semana 38 estou trabalhando com ASPIRE e quero falar sobre essa experiência.
Contexto
O primeiro ponto para a contextualização é que o Academia Pay não é um projeto para ser comercializado, vendido, ou ter clientes reais, nada disso.
O foco também não é “ensinar SaaS”!! (deus me livre!)
Longe de mim ter como cliente o usuário final. Eu gosto é de DEV!!!
É um “povinho complicado”, um “bicho de uma espécie exótica”, muito complexa, mas é minha tribo, minha galera, sangue do meu sangue!
O objetivo do Academia Pay é explorar um projeto o mais próximo do real possível, servindo muito mais como um segundo projeto de conclusão de curso, porém daqueles que você vai de ponta a ponta, da modelagem de banco à criação de abstrações, da infraestrutura aos design patterns, de system design a padrões de codificação e separação de projeto, com direito a implantação e lidar com toda a dinâmica e complexidade como se fosse produção.
O projeto é uma oportunidade de mostrar como os assuntos do Cloud Native .NET e Mensageria .NET se conectam para entregar um projeto real, visando uma entrega de produção. Enquanto o assunto SaaS, Gateway de Pagamento é o contexto, o pano de fundo, um escopo limitado bem delimitado.
Esse projeto cria uma oportunidade real de abordar:
- Problemas que demandam Lock distribuído
- Cache curto
- Paralelismo e concorrência
- RPC com AMQP
- Outbox Pattern
- Inbox Pattern
- Alocação dinâmica de infraestrutura (máquinas, containers, inicialização de tenant)
- Roteamento dinâmico
- Enfim trazer o conteúdo de SonarQube
- Refazer o conteúdo sobre Jenkins
Soluções e preocupações que tratam problemas reais de projetos de produção.
São assuntos que possuem pouca procura, portanto possuem pouco conteúdo, mas estão no canto cego de todo dev, e precisariam fazer parte do get started de qualquer dev sênior.
Assim é possível aumentar a quantidade de soluções possíveis, e dar mais versatilidade para o dev. Todos os problemas que os padrões resolvem são muito bem conhecidos e documentados, entretanto o elo que conecta o conteúdo acadêmico ao prático, parece inexistente, e meu papel aqui é conectar esses 2 pontos, dando vida ao problema e à solução.
Além de permitir à aqueles que querem ver como as arquiteturas são concebidas do zero, principalmente porque eles estão vendo na prática quantas vezes quebro, refaço, corrijo, lapido, refatoro, até chegar exatamente no estado de clareza que eu quero.
Enfim isso, não é um pitch de vendas, se quiser saber mais, o link está aqui.
Em resumo, a natureza do projeto e os desafios que ele apresenta ajudam a contar uma história e como resultado, conceber um produto completo, do zero.
Antes do Aspire
No passado já havíamos começado o eShop Cloud Native e esbarrei em um desafio chato ao abordar observabilidade.
Lá em 2013 eu consolidei o ELK Stack + RabbitMQ como uma nova stack que chamei de Enterprise Application Log.
O Enterprise Application Log é uma stack de logs, com aspirações à stack de observabilidade. O componente central da stack é o Elastic, enquanto a visualização era responsabilidade do Kibana. O RabbitMQ e LogStash e dão conta de reduzir a latência, aumentar a resiliência e assumiam respectivamente o papel de transporte e ingestão desses logs. Na stack, métricas e log eram unificados e implementados com base em logs com muitos metadados, enquanto não existia tracing presente na stack.
Tracing era um tema que nascia na mesma época em grandes empresas como Google, Twitter, Uber, entretanto era algo distante da nossa realidade para um projeto daquele tamanho, distribuição e criticidade.
The History of Distributed Tracing
Dapper, a large-scale distributed systems tracing infrastructure, was introduced by Google in 2010. Two years after Dapper was made public, Twitter open sourced Zipkin, which was designed for application performance tuning. Zipkin was the first open source distributed tracing project. Zipkin trace data can be collected and visualized using a UI. In 2015, Uber launched Jaeger, which was inspired by Dapper and named after the German word for hunter. Later in 2017, Uber published a blog post, called Evolving Distributed Tracing at Uber Engineering, explaining the reasons for the architectural choices in Jaeger. In addition to creating Jaeger, its author, Yuri Shkuro, wrote a book about distributed tracing called Mastering Distributed Tracing.
In 2016 Ben Sigelman, founder of Lightstep, wrote a blog post called Toward Turnkey Distributed Tracing, describing OpenTracing as a single standard. Some people refer to this as the OpenTracing Manifesto. OpenTracing allows developers of application code, open source packages and open source services to instrument their code without binding themselves to any particular tracing solution. The goal of OpenTracing was to solve a standardization problem. Trace context must pass through all the components, including application code, dependent libraries, standalone open source services (Nginx, MySQL) and other vendor-specific libraries and services, to collect a complete distributed trace. Collecting a full path without a standard API to define the collection and passing of trace context is difficult. OpenTracing aims to solve this problem by defining a standard API that can be implemented by components from different tracing solutions, allowing the collection of end-to-end tracing data. The Cloud Native Computing Foundation (CNCF) accepted OpenTracing as its third project in October 2016. Two months later, OpenTracing 1.0 was released. After OpenTracing, Jaeger joined the CNCF.
W3C tracing context specification was proposed in November 2019, bringing distributed tracing closer to standardization. Over ten years, distributed tracing evolved from one paper to an active community. With standardization on all the layers, it is moving from just tracing to overall observability, ranging from latency optimization to root cause analysis and application performance management. It is moving from a single backend system to an end-to-end solution that spans multiple systems.
OpenTracing and OpenTelemetry merged in 2019. Using OpenTelemetry, distributed tracing can be implemented end-to-end. It released version 1.0 in 2021. CNCF’s OpenTelemetry project is one of the fast-growing projects, and OpenTelemetry has become the de facto standard for tracing, metrics and logging.
O Enterprise Application Log sempre exigiu muito para rodar. Não muito para um servidor, mas muito par um desktop ou notebook de trabalho, principalmente com Windows que roda toda a stack com Docker no WSL. Isso fazia com que facilmente qualquer projeto que quisesse usar localmente a stack precisasse de ao menos 6gb de RAM só para a stack, muito para um desktop de desenvolvimento em 2013.
Claro que “o padrão” dos desktops evoluiu, mas vale lembrar que estamos falando em desktops que rodavam a stack no docker desktop com máquinas virtuais (Hyper-v Comuns, e mais tarde com WSL2), que por sua vez sempre recebem uma fração do hardware apenas.
Claro que subir uma infraestrutura de observabilidade compartilhada, é uma possibilidade, mas isso não faz sentido para um projeto dedicado à conscientização da comunidade. É preciso prever que cada um possa de subir na sua própria máquina. E essas demandas de hardware fazem com que seja uma realidade distante para a maioria.
Mas por que trazer observabilidade para a máquina do Dev?
O desenvolvedor é uma espécie de humano diferenciada, ele é limitado ao que ele toca, limitado ao que enxerga.
Se ele não fizer uso da observabilidade diariamente para extrair algum insight sobre o que está construindo, ele fará o mínimo e ignorará observabilidade.
Como se não bastasse sabotar o projeto, fazendo o mínimo, e produzindo muitos dados que não servem para nada, ele também consegue ser mais improdutivo e ineficiente.
Então ele não somente sabota o projeto, mas sabota a si mesmo.
E o pior? Não basta ensinar, ele precisa usar!
Por isso, mesmo que simplista e insuficiente para um ambiente de produção, o dashboard do Aspire é excelente para o workflow de desenvolvimento na máquina do dev. Porque entrega Logs, Trace e Métricas em um só componente que consome pouquíssimos recursos, e isso já é incrível.
.NET Aspire
Como o .NET Aspire se conecta a esse assunto?
Assim:
O .NET Aspire é composto por muitas coisas ao mesmo tempo, mas primeiro precisamos entender uma divisão macro que trata de diferenciar componentes que são passíveis de serem adotados em produção e componentes que são exclusivos do workflow de desenvolvimento e só existem na máquina do desenvolvedor.
Componentes de Desenvolvimento
Ferramentas de desenvolvimento, que não são implantados em produção.
- Orquestrador
- Dashboard
O Orquestrador foi projetado para ser usado no ambiente de desenvolvimento, ele casa muito bem com o Visual Studio embora em algum momento tenderá a poder ser executado no Linux também, por linha de comando, mas não tem a missão (nem capacidade) de substituir o Kubernetes, embora substitua com louvor o compose.
O fluxo de desenvolvimento foi pensado na substituição do compose, principalmente porque para quem usa Kubernetes, toda a stack do Compose só tem utilidade no desktop do desenvolvedor. Não servindo para nada em produção.
Já o Dashboard, opera 100% em memória.
Componentes de Produção
- Integrações (extensions para criar configurações dos mais variados serviços, com observabilidade e resiliência)
- Unificação das configurações de Resiliência e Observabilidade
- Extensions para Adicionar HealthCheck
- Service Discovery estático, baseado no mecanismo de configurações do ASP .NET
- Configuração de Telemetria
Onde está a vantagem?
Em produção temos um conjunto pré-moldado de componentes úteis. Eles lidam com configurações de observabilidade, service discovery, resiliência e nos ajuda a entregar melhor nossas soluções.
Já nos componentes de desenvolvimento, aqueles que não são implantados em produção, temos também características atraentes, como:
- Baixo Consumo de Recursos (em especial memória)
- Unificação das ferramentas
Docker ComposeGrafanaPrometheus / MimirJaeger / Tempo
- Abstração sobre o runtime de container, permitindo o uso do podman.
Porque escolhi o .NET Aspire no Academia Pay?
Existem alguns motivadores que gostaria de compartilhar contigo.
Observabilidade é segurança
A falta de uma boa estratégia de observabilidade produz como consequência o desconhecimento sobre como nossa aplicação está se comportando, que por sua vez se traduz mais tarde em insegurança e incerteza sobre como nosso código está se comportando.
Boa parte dos desenvolvedores que conheci não fazem a menor ideia do que é observabilidade de verdade. Eles nunca refatoraram nenhuma aplicação para adicionar contexto aos logs, métricas e tracing, de forma que pudessem tirar proveito dessas informações mais tarde.
A maioria acha feio, um código observável.
Assim, para a maioria das aplicações que possuem alguma configuração de observabilidade, 90% do log, métricas e tracing é lixo inútil.
Eles não estão errados, o log sem contexto não serve de nada.
Se você só habilita uma flag aqui ou acolá, ou apenas adiciona OpenTelemetry ou qualquer configuração de observabilidade centralizada no Program.cs, sem refatorar a aplicação para adicionar contexto, você também faz parte dessa massa que não conhece observabilidade de fato.
Então esse era um excelente momento para falar de observabilidade, com um projeto “real”, e não como um módulo de um curso. Entretanto, o Enterprise Application Log não seria a melhor opção para um ambiente de desenvolvimento, enquanto o dashboard do aspire resolveria com graciosidade!
Outro ponto, é que o Enterprise Application Log faz tudo com base em Logs, já o Aspire adota o OpenTelemetry, que é uma abordagem mais nova, de 2019, mais abrangente, que separa Trace, Métricas e Logs em um padrão, um standard, adotado pelos principais players. Isso faz do Enterprise Application Log, finalmente, obsoleto, ultrapassado.
Assim, teríamos o próprio Aspire, para o nosso ambiente de desenvolvimento local, enquanto em produção, teríamos a stack completa da Grafana, o LGTM:
- Loki – Logs
- Grafana – Dashboards
- Tempo – Tracing
- Mimir – Métricas
O LGTM substituiria o dashboard do Aspire em produção, enquanto Docker Swarm (em 2024) e Kubernetes (2025 ou 2026) substituiria o orquestrador, já que o Orquestrador do Aspire nunca teve aspirações para se tornar um componente de produção e o dashboard do Aspire também não é um projeto para ser usado em produção.
Aliás, sobre o Dashboard, aqui temos alguns motivos para que ele não seja um projeto de produção:
- Armazenamento
- ele não tem um banco de dados
- todos os dados ficam em memória
- tem um limite de dados que você configura (x métricas, y trace, z logs)
- Valores padrão:
Dashboard:TelemetryLimits:MaxLogCount
| 10,000 | The maximum number of log entries. Limit is shared across resources.Dashboard:TelemetryLimits:MaxTraceCount
| 10,000 | The maximum number of log traces. Limit is shared across resources.Dashboard:TelemetryLimits:MaxMetricsCount
| 50,000 | The maximum number of metric data points. Limit is per-resource.
- Usabilidade
- A usabilidade é limitada
- O dashboard não é customizável
- Não pode criar novos dashboard
- Não permite criar novas queries
- Não tem alertas
- Não permite mesclar fontes de dados
Esses são os principais motivos para sequer cogitar o uso do Dashboard do Aspire em produção, então mais que natural pensar, mesmo que em um projeto de referência, em como adotar o LGTM em produção, enquanto o dashboard do aspire cuida do desktop de desenvolvimento.
E se talvez você se pergunte: Ok, mas não vale a pena usar outra coisa em desenvolvimento? Algo mais próximo à produção?
O dashboard do Aspire entrega:
- 1 Só documentação
- 1 Só produto/projeto
- 1 Só linha de pensamento
- 1 Só componente para estudar
Então o esforço cognitivo para lidar com Aspire é mínimo, e os ganhos são monumentais se comparados com o esforço.
Pontos negativos
O distanciamento do docker ou das aplicações .NET desde o dia 1 do desenvolvimento passou a ser um novo desafio.
Com o Orquestrador do Aspire, o dev não precisa tocar no Docker quase nunca, e isso é realmente um ponto ruim.
Em um contexto Cloud Native, essa realidade só existe quando você é uma pequena parte de uma engrenagem muito maior e sua responsabilidade está limitada a escrever código e fazer commit.
Estamos há anos, (e eu estou desde 2016), dizendo:
Hey,
dê atenção ao entendimento de Linux
dê atenção ao entendimento de Containers
dê atenção ao Docker!
dê atenção à observabilidade, isso vai fazer falta
Exatamente para que experiências como a apresentada abaixo não acontecessem.
O que tem um quê de lamentável, pois até hoje 100% dos problemas que vi com Docker no Windows ou na experiência com projetos .NET eram problemas sobre:
- Expectativa desbalanceada / equivocada
- Preguiça de estudar o que está usando para entender o que é certo que não vai dar certo ou que é instável
- Desconhecimento
E quando a gente fala de instabilidade, estamos falando quase que exclusivamente do mapeamento de arquivos no file system.
O problema não é do docker, é que você usou uma furadeira conectada com uma extensão, e essa extensão não suporta a amperagem que uma furadeira precisa. E, portanto, esquenta e desarma o disjuntor.
É isso que acontece com volumes com docker: Quando você faz o mapeamento do seu disco C, D, E, para um container Linux, você está fazendo com que o docker desktop suba um processo de sync, com o docker Daemon que está no Linux, usando um protocolo de rede, ha pouco tempo era gRPC (http2 streams) com gRPC Fuse FS
https://www.docker.com/blog/deep-dive-into-new-docker-desktop-filesharing-implementation
Se você entende isso, você está na frente de todos que reclamam do Docker no Windows.
TODOS!!!!!!!!!!
Portanto, Tweets e comentários como esses, atestam muito mais sobre quem teceu tal comentário do que sobre a solução em si.
Até porque tenho uma massa significativa de alunos que não reclamam, porque entendem como as coisas acontecem por baixo do capô para não criar expectativas descabidas.
Por outro lado, esses mesmos alunos aprendem a contornar riscos e limitação adotando a estratégia certa em cada cenário, seja no windows ou no linux (cada um tem suas peculiaridades que merecem atenção).
Mas e o Aspire?
A experiência com o .NET Aspire é incrível para colocar profissionais jovens que não conhecem containers, prontos para construir aplicações cloud native.
.NET Aspire casa com a separação rígida em Dev e DevOps, casa com a ideia de um time cuidado de dockerfile e tudo relacionado à dockerização das aplicações.
Isso é útil, mas é a contramão do que há quase 10 anos defendo.
A Microsoft está resolvendo com ele alguns problemas do mercado:
- Necessidade de conhecimento específico sobre containers para trabalhar com .NET Cloud Native
- Dificuldade de achar esses perfis
- Dificuldade de aproveitar o Desenvolvedor Treinee ou Jr. que vem de bootcamps e formações rápidas
- Frear o Cloud exit, resultado do fracasso dos projetos de lift and shift de adoção de cloud.
- Viabilizar a adoção de Kubernetes 100% gerenciado com o Azure Container Apps, permitindo que empresas que não dominam e nunca adotariam Kubernetes, passem a usá-lo sob uma camada PaaS, não agnóstica.
- Facilitar a adoção de Kubernetes para aqueles que querem se manter em uma experiência agnóstica, entretanto possuem pouco conhecimento a respeito de como manter um ambiente Kubernetes em produção.
No final das contas a Microsoft está fazendo um excelente trabalho atendendo uma demanda que surgiu com a pandemia.
O distanciamento dos devs jovens, que sofrem com a concorrência excessiva, e as vagas que não são fechadas por falta de skill é reduzido com esse tipo de solução.
Quanto menos skill for necessário, mais fácil fica flexibilizar no processo seletivo.
Isso ajuda muito um perfil de empresa que pode se dar ao luxo de realizar esse tipo de troca, para essas, ou abraça essa estratégia, ou não consegue atender novos clientes e projetos.
Minha opinião
.NET Aspire é uma resposta a uma demanda do mercado.
.NET Aspire ajuda o desenvolvedor a ser mais produtivo.
.NET Aspire não é só o dashboard, nem só o orquestrador, os demais recursos são importantes e úteis para nosso dia-a-dia de produção.
Resolve uma demanda do mercado.
Substitui o Docker Compose por uma solução que faz sentido quando estamos mirando para o deploy no Kubernetes.
Mas mantém devs na zona de conforto, ignorando o estudo sobre containers, o que é um problema e produz bizarrices como aquela que vimos no tweet.
Mas, isso não é problema que ela deva se preocupar, até porque, quanto mais conhecimento, mais possibilidades de deployment de kubernetes ficam disponíveis, que exige mais conhecimento…
No próximo post falarei sobre como ignorar o Orquestrador do .NET Aspire e trazer toda a experiência do Aspire para projetos .NET baseados em Docker Compose, usando, inclusive, o Dashboard do .NET Aspire.
0 comentários