No QCon Nova Iorque 2018, Michael Bryzek apresentou como projetar arquiteturas de microservices "do jeito certo". Alguns dos pontos importantes abordados foram: engenheiros devem projetar primeiro o esquema para todas as APIs e eventos, já que isso permite a geração de código automatizado de código repetitivo; streams de eventos devem ser inscritos ao invés de chamar diretamente as APIs; investimentos devem ser feitos em automação, como implantação e gestão de dependências; e a equipe de engenharia deve focar na escrita de testes simples e eficazes, que melhoram a qualidade, agiliza a manutenção e permite entregas contínuas.
Bryzek, co-fundador, presidente e CTO da Flow.io (anteriormente co-fundador da Gilt), começou sua palestra compartilhando uma piada pessoal sobre uma solicitação para alterar uma URL dentro de um sistema, do padrão 'foo.com/latest/bar.js' para 'foo.com/1.5.3/bar.js' e recebeu a resposta que "tomaria semanas para ser feita" e que a equipe não tinha os recursos necessários. Intrigado porque uma simples alteração no formato de uma URL demandava tanto trabalho, descobriu que a URL foi implementada numa biblioteca, e centenas de serviços dependentes precisavam ser atualizados, alguns dos quais não eram atualizados há anos, e demandaria atualizações de dependências adicionais para permitir a construção e a implementação.
A piada foi um simples exemplo de "arquiteturas nem tão boas" onde se escolhe a opção mais rápida sem prever estagnações futuras. Em contraste, uma ótima arquitetura deve ajudar ativamente a escalar equipes de desenvolvimento, entregando qualidade e permitindo alta performance e baixo custo, enquanto suporta naturalmente funcionalidades futuras. A arquitetura de microservices é um estilo moderno e popular de implementar sistemas, mas que precisa ser projetada do jeito certo; engenheiros devem se esforçar não para projetar sistemas do tipo "spaghetti" e sim visar uma abordagem em camadas.
Depois, Bryzek apresentou uma série de equívocos comuns com microservices. O primeiro equívoco apresentado foi o de que "microservices permitem que equipes escolham as melhores linguagens de programação e frameworks para suas tarefas". A verdade é que isto pode custar caro, e o tamanho da equipe e investimentos são fatores críticos na decisão de suportar outra linguagem dentro da pilha de tecnologia.
Se olhamos o Google como uma empresa de engenharia geralmente ótima, ela tem entre 20.000 e 30.000 engenheiros e pelo menos 8 linguagens de programação. Então gosto de dizer [adote] uma linguagem de programação para cada 4.000 engenheiros [dentro da sua empresa].
O segundo equívoco discutido foi a "geração de código é do mal". Entretanto, a realidade é que "criar um esquema definido que é 100% confiável" é importante para os recursos e eventos, e assim, a geração de código pode ser muito útil para escalar os esforços de desenvolvimento e a manutenção. O terceiro equívoco trazido, "os logs de eventos devem ser a fonte da verdade", foi comparado contra a realidade de que eventos são partes críticas de uma interface, mas está "ok os serviços serem o sistema de registro de seus recursos". O último equívoco, "desenvolvedores não podem manter mais que três serviços cada", foi rebatido com uma discussão de que na verdade esta é uma métrica errada. Quando feito corretamente, apontou Bryzek, é onde a "automatização brilha"; desenvolvedores na Flow.io mantêm em média 5 serviços cada, e semanalmente a manutenção leva menos de 5% de seu tempo.
Na sequência, foi apresentado um tour pela arquitetura da Flow.io. Isto incluiu uma visão sobre o esquema de definição de API orientada a recursos, escrito no formato JSON, que permite que tudo seja definido, de entidades e propriedades correspondentes, em conjunto com os metadados apropriados. Os arquivos de definição de esquemas são armazenados dentro do Git DVCS e a entrega contínua é praticada. Uma série de testes aplicam consistência em todo o conjunto de APIs, e agem efetivamente como uma ferramenta avançada de verificação de erros. O objetivo com tais testes deveria resultar em engenheiros acreditando que "esta pessoa escreveu toda a API".
A equipe de engenharia usa a ferramenta de código aberto apibuilder.io em conjunto com seus testes para ajudar a evitar erros e verificar mudanças que potencialmente podem quebrar algo durante a fase de projeto da API. Os utilitários de linha de comando da ferramenta apibuilder permitem a geração e atualização de códigos associados com recursos das APIs e suas rotas (inicialmente escrito com o framework Play 2 na Flow.io). Um código do cliente da API também pode ser auto-gerado, incluindo a geração de um simulador de cliente que permite testes fiéis e rápidos. Bryzek informou que, dentro da arquitetura do Flow.io, o sistema de registro é a especificação da API; a geração de código assegura que a equipe "realmente adere a especificação".
Ao discutir sobre a arquitetura de banco de dados, foi sugerido que cada aplicação contida num microservice tenha seu próprio banco. Nenhum outro serviço é permitido acessar outro banco de dados diretamente; outros serviços devem usar somente a interface ao serviço alvo, que consiste da API provida e um stream de eventos. A equipe de engenharia da Flow.io tem investido pesado na criação de uma ferramenta única de linha de comando para "dev" usada para gerenciar toda a infraestrutura e tarefas comuns de desenvolvimento. Um banco de dados pode ser criado (usando o AWS RDS no exemplo apresentado) por um único comando. Todos os requisitos de armazenamento são definidos usando um esquema no formato JSON, que embora seja independente do esquema da API associada, usa as mesmas ferramentas. Operações de DDL e de configuração no banco de dados como criação de tabelas são auto-geradas, assim como o código da aplicação do serviço cliente Objeto de Acesso aos Dados (DAO, em inglês). Isto permite normalizar o acesso ao banco de dados e assegura que os índices corretos sejam criados desde o início.
A próxima seção da apresentação focou na implementação de código, que engatilha a criação de uma tag Git relacionada ao que foi codificado. Estas tags são criadas automaticamente por uma mudança na árvore mestre (por exemplo, a solicitação para unir duas árvores no Git) e são 100% automatizadas e 100% confiáveis. Bryzek demonstrou o sistema de gestão de entrega contínua da Flow.io, o "delta" (cujo código está disponível no GitHub) e descreveu o quão importante acredita ser esta prática.
A Entrega Contínua é um pré-requisito para gerenciar arquiteturas de microservices.
A definição da infraestrutura necessária para cada microservice é simples, e fica registrada num único arquivo no formato YAML que define o tipo da instância, quais portas serão abertas e a versão de configuração do sistema operacional. Todos os serviços dentro de uma instância expõem um endereço padrão chamado 'checagem da saúde' do sistema, no qual se permite que todos os sistemas de implantação, observação e alertas determinem seus estados.
Em seguida, Bryzek falou sobre a importância de eventos e streaming de eventos. Diversos terceiros solicitam acesso à API da Flow.io e ele responde: "temos uma API fantástica, mas, por favor, registrem-se para receber nossos streams de eventos". Os princípios chaves para uma interface de eventos incluem: a provisão de um esquema de primeira classe para todos os eventos; os produtores garantem pelo menos uma entrega; e os consumidores implementam idempotência. Dentro da arquitetura da Flow.io, a latência de um único evento de ponta-a-ponta é de aproximadamente 500 milissegundos e a implementação é baseada no PostgreSQL, que é escalado para aproximadamente 1 bilhão de eventos por dia por serviço.
A abordagem orientada a eventos significa que os produtores criam um diário de todas as operações executadas nas tabelas do banco de dados para registrar as inserções, atualizações, remoções, etc. Uma vez criado um evento, um registro no diário correspondente é enfileirado para ser publicado. Isto acontece em tempo real, é assíncrono e um único evento por registro no diário é publicado. O re-envio de um evento de um serviço é feito simplesmente ao enfileirar novamente os registros do diário. Os consumidores armazenam novos registros num banco de dados local que é particionado para rápida remoção. Assim que chega um evento, um registro é enfileirado para ser consumido. Eventos são processados em pequenos lotes com um período padrão de 250 milissegundos entre cada tentativa de consumo. Quaisquer falhas são registradas localmente. Mais informações e códigos exemplos desta abordagem podem ser encontrados no repositório db-journalling da Gilt Technology. Os leitores interessados também podem explorar o conceito similar de Captura de Alteração de Dados (CDC, em inglês), e um exemplo de tecnologia open source sobre o assunto é o Debezium.
A seção final da apresentação focou na gestão de dependências e em "como manter as coisas atualizadas". O objetivo deve seratualizar todos os serviços regularmente e automaticamente para usarem a última versão em suas dependências; isto é crítico para correções de segurança e defeitos em bibliotecas centrais. Referindo-se novamente à sua anedota do início, Bryzek disse que "isso deve levar horas, não semanas ou meses" e o mesmo processo deve usado para bibliotecas desenvolvidas internamente como open source externas. A equipe de engenharia da Flow.io melhora todos os serviços todas semanas para as últimas dependências e a equipe utiliza sua ferramenta "flowcommerce/dependency" (liberada como open source) para rastreio de dependências. A ferramenta inicia melhorias automatizadas dentro da base de código de um serviço junto com a criação de uma solicitação de alteração. Cada serviço é publicado tão logo o processo de criação termine.
Resumindo a apresentação, Bryzek disse que engenheiros devem projetar primeiro o esquema para todas as APIs e eventos, e os eventos devem ser consumidos ao invés de chamados diretamente por APIs. Os engenheiros devem investir na automação apropriada e efetiva, focando em tarefas como implantação, criação de código e gestão de dependências. As equipes devem também serem encorajadas e habilitadas para escrever testes "fantásticos e simples" já que isso leva à qualidade, manutenção ágil e permite entregas contínuas.
Os slides da apresentação de Michael Bryzek no QCon Nova Iorque "Projetando arquiteturas de microservices do jeito certo" podem ser encontrados no SlideShare. O vídeo da apresentação, bem como todas as apresentações do QCon Nova Iorque serão liberadas no InfoQ.com nos próximos meses.