Microservice: Todo mundo comete erros – Parte 2

Todo mundo comete erros. Os sábios não são aqueles que nunca cometem erros, mas aqueles que se perdoam e aprendem com seus erros.” — Ajahn Brahm (físico teórico, autor, e monge Budista)

Nesta segunda parte, voltamos ao esforço de fornecer, talvez para as pessoas sábias, um atalho para “aprender com seus erros” ao aplicar microservices (se houver atalhos). A primeira parte foi focada nos erros no projeto de aplicações [1], enquanto a segunda e última parte está focada nos erros de arquitetura.

De fato, um dado sistema que aplica microservices é um sistema distribuído por definição; consequentemente, os erros arquiteturais estão profundamente relacionados às falácias da computação distribuída [2] e ao seu impacto nas “-ilities”.

_______________________________________________________________________________________________________________________________________________________

Primeiro Erro – Evitar o “Discurso Correto” ou a legitimação de conversas ociosas

 Um praticante comprometido com o “Discurso Corretose abstém das conversas ociosas. No campo dos microservices, um erro comum é permitir que o sistema intrinsecamente distribuído seja projetado usando uma “mentalidade monolítica” chamada de “procedure-call-PC“, em poucas palavras, “sempre que necessário, faça uma chamada de procedimento remoto usando REST sobre HTTP / S ”, o que certamente leva a conversas ociosas.

Esse erro tem uma estreita relação com os erros explorados na primeira parte, em particular com o ‘Segundo erro – O evitar do  “Caminho do Meio” ou sobre o tamanho errado do escopo dos microservices‘ [1]. De fato, ele funciona como um “endosso técnico” para permitir comunicações excessivas entre serviços e evitar perguntas que surgem naturalmente sobre a complexidades da comunicação entre serviços, por exemplo, “por que precisamos usar uma chamada REST por HTTPS para recuperar os gêneros? qual é a frequência de mudança de gêneros? devo armazenar em cache localmente esses dados? qual é o SLA do serviço de gêneros?“.

As consequências das conversas ociosas, incluindo as lideradas pela “mentalidade monolítica”, são DESASTROSOS em um sistema distribuído, pois o número de serviços que colaboram para uma determinada função comercial pode ser alto e as chamadas de rede podem falhar (Falácia 1. A rede é confiável), que por sua vez é o que compromete a confiabilidade geral do sistema (um conjunto de componentes acoplados em série tem sua confiabilidade definida pela multiplicação das confiabilidade de seus componentes). Além disso, como o número de serviços é alto, a latência da rede (Falácia 2. A latência é zero), bem como a serialização e deserialização de mensagens trocadas (Falácia 7. O custo de transporte é zero) compromete severamente a capacidade de resposta, em particular, nos picos de utilização. Além disso, na utilização de pico, a largura de banda pode impor problemas severos em uma rede não local (Falácia 3. A largura de banda é infinita).

Uma vez estabelecido o CENÁRIO DESASTROSO, evitando o “Discurso Correto”, é comum ver uma maior disseminação do erro na análise (sempre um sinal de alerta para os sábios):

(1) para lidar com a Falácia 1. A rede é confiável, enfatiza-se o uso de tempos limite (timeouts), novas tentativas automáticas (retries) e, talvez, circuit-breakers.

(2) para lidar com a Falácia 2. A latência é zero, preconiza-se o cache local. Além disso, quando o volume de dados a serem armazenados em cache é “muito grande”, a preconização leva ao conceito de “cache aquecido”.

(3) para gerenciar a Falácia 7. O custo do transporte é zero, enfatiza-se mais os protocolos de transporte do que o projeto e análise da comunicação entre serviços.

(4) para cuidar da Falácia 3. A largura de banda é infinita, além do conceito de cache local, sugere-se políticas de limitação (throttling).

Embora essas sejam preocupações importantes em um sistema distribuído bem arquitetado, elas não aumentam a confiabilidade e a capacidade de resposta do sistema exclusivamente. Por outro lado, o compromisso com o “Discurso Correto” pode significar: evitar serviços muito pequenos (‘Segundo erro – O evitar do  “Caminho do Meio” ou sobre o tamanho errado do escopo dos microservices ‘[1]), esforçar-se por cargas úteis razoáveis, usar operações em massa, considerar a topologia de rede (Falácias 5. A topologia não muda e 8. A rede é homogênea), selecionar a abordagem correta para a comunicação entre serviços em cada caso, etc. …

Há alegações de que os eventos e as ferramentas relacionadas, por exemplo, um broker com alta disponibilidade, podem lidar com todas as necessidades de comunicações entre serviços. Eventos usam dois chapéus: (1) um chapéu de notificação que aciona serviços e (2) um chapéu de replicação que copia dados de um serviço para outro [7]. Embora a comunicação entre serviços possa ser bem tratada pelo último chapéu (o de replicação), as conversas ociosas ainda representam um grande desafio para o chapéu anterior, pois estão profundamente relacionadas ao conceito de transação comercial (veja o próximo erro).

Segundo Erro – Evitar a “Resolução Correta” ou o vício em ÁCIDOS (ACID)

Um profissional comprometido com a “Resolução Correta” resolve sair de casa. Aqui, no sentido de que ele deixa sua zona de conforto. No campo dos microservices, um erro comum é o vício em ácidos (ACID, atomicidade, consistência, isolamento, durabilidade), que é confortável para profissionais de negócios e técnicos.

O ACID é um conjunto de propriedades das transações de “gerenciamento de estado” destinadas a garantir a validade, mesmo em caso de erros, falhas de energia, etc.… Dentro dos limites de um determinado microservice, o ACID é facilmente alcançado com base nas “ferramentas de gerenciamento de estado” como os clássicos bancos de dados SQL ou as ferramentas NewSQL.

Em um sistema distribuído, transações distribuídas seriam necessárias entre microservices o que remonta ao vício em ácidos (ACID). De fato, “muito tempo foi desperdiçado por organizações de todas as formas e tamanhos, tentando preservar a noção de transações semelhantes a bancos de dados em serviços independentes. No final, nunca funciona, desperdiçando tempo e dinheiro” [3]. Consequentemente, consistência eventual deve ser aplicada.

Os microservices eventualmente consistentes são conhecidos por fornecer bases (BASE  – basicamente disponível e eventualmente consistente), em contraste ao vício em ácidos (ACID).

Além disso, “em um sistema que não pode contar com transações distribuídas, o gerenciamento da incerteza deve ser implementado na lógica de negócios” [4]. Portanto, a lógica de negócios deve ser projetada / analisada considerando as complexidades do estado, o que inclui, pelo menos, a compreensão da forma dos dados e como eles evoluem durante o ciclo de vida de negócio e também durante a cooperação entre serviços. Essa gestão da incerteza deve refletir-se adequadamente nas funcionalidades de negócio, ou seja, os profissionais de negócios são responsáveis ​​pela consistência do estado.

Terceiro erro – evitar a “Ação Correta” ou simplificar a segurança

Um praticante comprometido com a “Ação Correta” se abstém de roubar. No campo dos microservices, um erro estreitamente relacionado é simplificar demais a preocupação com a segurança (Falácia 4. A rede é segura).

Na prática, existem “pontos de vista extremos”. Por um lado, afirma-se que a segurança é fornecida pela infraestrutura e, consequentemente, nenhuma preocupação deve ser levada em consideração no próprio sistema distribuído. Por outro lado, profissionais argumentam que cada comunicação requer uma autorização independente, o que é uma consequência do primeiro erro (a legitimação da conversa ociosa). Mais uma vez, o “Caminho do Meio” deve ser a orientação, a qual está baseada em um ou mais grant types do OAuth2.

Quarto erro – Evitar o “Meio de Vida Correto” ou a falta de foco no valor de negócio

Um praticante comprometido com o “Meio de Vida Corretoevita causar sofrimento aos seres sencientes de qualquer maneira. No campo dos microservices, um erro comum é a falta de foco no valor de negócio, o que claramente pode levar ao sofrimento dos usuários de negócio (geralmente, o mais sensível da cadeia de valor).

No primeiro erro desta segunda parte, o comprometimento da confiabilidade foi explorado em relação à Falácia 1. A rede é confiável e outras. Além disso, o segundo erro também pode comprometer a confiabilidade, pois pode haver falhas de projeto ou de implementação no “gerenciamento da incerteza de estado”, inerentemente presente em um sistema distribuído. Além disso, para lidar com a Falácia 5. A topologia não muda, é preciso aplicar algum tipo de serviço de nomes com alta disponibilidade (por exemplo, Kubernetes Service Discovery, Eureka, etc …), que por sua vez é assunto da mesma preocupação, qual seja “gestão da incerteza do estado”.

Além da confiabilidade, uma das principais causas de sofrimento é a falta de ênfase nas preocupações de escalabilidade. Como os microservices não possuem estado, eles são adequados para escalar, enquanto as “ferramentas de gerenciamento de estado” representam desafios [5], mais uma vez, devido ao “gerenciamento da incerteza de estado”. No entanto, mesmo a escalabilidade dos microservices pode ser facilmente comprometida por uma análise ingênua. Por exemplo, em um projeto real, como o sizing padrão, na documentação do fornecedor [6], é limitar o número de pods por cada core (PodsPerCore) a 10 (dez), então um arquiteto concluiu que cada pod deve limitar-se a usar 100 millicores, o que compromete a escalabilidade e a capacidade de resposta.

Finalmente, a capacidade de resposta do sistema distribuído resultante é a combinação de todas as preocupações anteriormente exploradas e outras como disponibilidade de recursos.

Quinto Erro – Evitar a “Atenção Correta” ou a falta de observabilidade

Um praticante comprometido com a “Atenção Corretaestá consciente do que está fazendo. Um sistema distribuído “sempre será mais complexo de implementar e operar do que um aplicativo monolito simples projetado para executar a mesma lógica” [7]; portanto, no campo dos microservices, um erro comum é a falta de observabilidade ou, em outras palavras, a falta de consciência do que o sistema distribuído está fazendo.

É comum ouvir dos arquitetos, no mundo real, que a observabilidade é desejada, mas não é um requisito, no sentido de que a área de operações trabalha há anos e talvez logs descentralizados forneçam todas as informações necessárias. No entanto, como afirmado anteriormente, os microservices requerem consciência do que o sistema distribuído está fazendo, o que só é alcançado através de um conjunto de ferramentas que forneçam observabilidade.

Em particular, a observabilidade é fornecida por ferramentas de “service mesh” (por exemplo, Istio, Linkerd, etc.) trabalhando em conjunto com “distributed tracing” (por exemplo, Jaeger, Zipkin, etc.), que se tornaram predominantes em ambientes maduros de microservices. Essas ferramentas são o local para (1) monitoramento da integridade do sistema, (2) solução de problemas, (3) imposição de políticas de comunicação entre serviços como tempo limite, retentativas automáticas, circuit-breakers, armazenamento em cache, throttling, etc…, (4) confiabilidade de ambientes produtivos e (5) a avaliação de versões alternativas no ambiente de produção (por exemplo, implantações azul / verde, teste A / B, etc.). Eles são os locais centrais para monitorar, rastrear e controlar a comunicação entre serviços – como eles estão conectados, executados e protegidos.

Conclusão

Concluindo, considere um cenário em que uma combinação de parte desses erros comuns esteja em vigor. Em tal possível cenário, de fato, um cenário do mundo real, uma chamada REST para o serviço de gêneros é usada por várias transações comerciais, que por sua vez têm sua capacidade de resposta definida pelo serviço dos gêneros, além de sua confiabilidade. Além disso, falhas na chamada do serviço de gêneros se propagam diretamente para as transações comerciais, aumentando a inconsistência temporária do estado (se o sistema distribuído projetado não exibir falhas na consistência eventual, definida pelo negócio) e causando uma falha global. Na presença de falhas globais, o valor de negócio do sistema distribuído foi comprometido e, consequentemente, algum tipo de sofrimento é imposto ao ser mais sensível da cadeia de valor, o usuário de negócio. Por fim, como não há preocupação com a observabilidade, consome-se tempo para rastrear essas falhas globais para o problema na chamada do serviço de gêneros, o que piora o sofrimento dos usuários de negócio. Um cenário tão desastroso pode até ser piorado por arquitetos que trabalham ativamente na “legitimação de conversas ociosas“, por exemplo, sugerindo um “cache aquecido” para as chamadas do serviço de gêneros.

Esta segunda e última parte da série “Microservice: todos cometem erros” apresentou os cinco erros mais comuns e gerais cometidos com microservices em relação às preocupações arquiteturais. Talvez, para as pessoas sábias, eles sejam um atalho para “aprender com seus erros” usando cinco dos oito caminhos possíveis.

Referências

[1] Microservice: Everyone Makes Mistakes — Part I

[2] Fallacies of Distributed Computing Explained

[3] Microservices Done Right, Part 1: Avoid the Antipatterns!

[4] Life Beyond Distributed Transactions, Pat Helland, 2007

[5] High-availability resides in the Backing Services

[6] Planning OpenShift — Sizing

[7] Designing Event-Driven Systems — Concepts and Patterns for Streaming Services with Apache Kafka, Ben Stopford, 2018