Os aplicativos baseados na Web vieram há muito tempo desde que costumávamos servir conteúdo HTML estático de servidores. Hoje em dia, os aplicativos são muito mais complexos e usam múltiplas estruturas, data centers e tecnologias. Nos últimos dois anos, vimos dois conceitos dominarem o mercado de TI:
movendo nossos aplicativos para a nuvem;
implantação de uma arquitetura de microsserviços;
Essas ideias moldaram a forma como projetamos e construímos softwares. De certa forma, não estamos mais construindo aplicações; em vez disso, estamos construindo plataformas. Os aplicativos não compartilham mais o mesmo espaço computacional. Em vez disso, eles têm que se comunicar uns com os outros através de protocolos de comunicação leves, como APIs REST ou chamadas RPC. Esse modelo possibilitou a criação de alguns softwares incríveis como Facebook, Netflix, Uber e tantos outros.
Neste artigo, discutiremos alguns dos problemas que impulsionam a inovação no desenvolvimento da web moderna. Em seguida, mergulharemos no básico da arquitetura orientada a eventos (EDA), que tenta resolver esses problemas pensando na arquitetura back-end de uma maneira nova.
Os problemas enfrentados pela teia moderna
Cada tecnologia tem que lidar com os desafios que os aplicativos sempre on, multi-usuário e assíncronsos enfrentam hoje:
Disponibilidade
Em vez de um aplicativo, agora temos muitas, dezenas talvez até centenas de serviços vinculados, e cada um deles tem que estar pronto para fazer seu trabalho 24 horas por dia, 7 dias por semana. Como podemos fazer isso? Na maioria das vezes, o serviço é dimensionado horizontalmente para várias instâncias, às vezes em vários data centers, tornando-o altamente disponível. Todas as solicitações que entrarem neste serviço específico serão encaminhadas uniformemente em todas as instâncias. Algumas ferramentas de implantação oferecem recursos de auto-recuperação, portanto, se uma instância cair, criará outra instância para tomar seu lugar.
Escalabilidade
A escalabilidade tem muito em comum com a disponibilidade. A disponibilidade é para garantir que haja pelo menos uma instância do serviço em funcionamento, pronta para atender às solicitações recebidas. A escalabilidade, por outro lado, é focada no desempenho. Se um aplicativo estiver sobrecarregado, então podemos criar novas instâncias desse aplicativo para acomodar o aumento do número de solicitações. Mas escalar aplicativos não é livre de desafios, especialmente se lidarmos com aplicações imponentes.
Única fonte de verdade
Antes dos microsserviços, este trabalho era simples. Todos os dados residiam em um único lugar, tipicamente algum tipo de banco de dados relacional. Mas quando vários serviços compartilham um banco de dados, você pode criar problemas como dependências entre equipes sobre mudanças de esquema ou problemas de desempenho. Um padrão comum para resolver esse problema é usar um banco de dados por serviço. Uma fonte distribuída de verdade realmente ajuda a manter a arquitetura limpa, mas agora temos que lidar com transações distribuídas e a complexidade de manter vários bancos de dados.
Síncrono
Em um cenário típico de solicitação-resposta, o cliente aguarda a resposta do servidor; bloqueia todas as suas atividades até receber uma resposta ou o tempo limite expirar. Se pegarmos esse comportamento e colocá-lo em uma arquitetura de microsserviços usando chamadas acorrentadas em todo o sistema, podemos facilmente acabar com o que eu chamo de "Inferno de Microserviços". Tudo começa com uma chamada de serviço, vamos chamá-lo de serviço A. Mas então, o serviço A precisa chamar o serviço B, e a diversão continua. O problema com esse comportamento é que se um serviço tem recursos bloqueados (por exemplo: um segmento está pendurado), os tempos limite agora são exponenciais. Se permitirmos um tempo limite de 500 ms por serviço e houver cinco chamadas de serviço na cadeia, então o primeiro serviço precisaria ter um intervalo de 2500 ms (2,5 segundos), enquanto o último serviço precisaria ter um tempo limite de 500 ms.
Introdução da arquitetura orientada a eventos
A arquitetura orientada a eventos (EDA)é um paradigma de arquitetura de software que promove a produção, detecção, consumo e reação a eventos .
-Wikipédia
Nos aplicativos clássicos de três níveis, o núcleo do nosso sistema era a base de dados. No EDA, o foco é deslocado para os eventos e como eles estão fluindo através do sistema. Essa mudança nos permitiu mudar completamente a forma como projetamos aplicativos que abordam os problemas mencionados acima.
Antes de realmente ver como o EDA faz isso, vamos ver o que exatamente é um evento. Um evento é uma ação que desencadeia uma notificação ou algum tipo de mudança no estado do aplicativo. Uma luz foi acesa(notificação),o termostato desligou o sistema de aquecimento(notificação),um usuário alterou seu endereço(mudança de estado)ou um de seus amigos mudou seu número de telefone(mudança de estado). Todos esses são eventos, mas isso não significa que devemos adicioná-los a uma solução orientada a eventos. Para que um evento seja adicionado, ele deve ser relevante para o negócio. Um usuário que faz um novo pedido é um evento relevante para esse negócio específico, mas ele/ela comer pizza no almoço não é.
Quais eventos são relevantes para um negócio pode ser óbvio quando você pensa sobre eles, mas alguns deles podem não. Especialmente aqueles eventos que ocorrem como uma reação a outros eventos. Para descobrir eventos que estão fluindo através do sistema, use uma técnica chamada Event Storming. Reunir os stakeholders em um aplicativo (de engenheiros de software a pessoas de negócios e especialistas em domínios) e mapear todos os processos de negócios como eventos específicos. Depois que todos os processos de negócios são mapeados, o resultado pode ser usado pelas equipes de engenharia como requisitos para construir suas aplicações.
Tendo descoberto quais são os eventos e como eles podem ser identificados, vamos dar uma olhada sobre como eles podem resolver os problemas comuns mencionados anteriormente.
Os eventos fluem em uma única direção, de um produtor para um consumidor. Compare isso com uma chamada REST. O produtor de eventos nunca espera uma resposta do consumidor, enquanto em uma chamada REST sempre haverá uma resposta. Sem resposta, sem necessidade de bloquear a execução do código até que algo mais aconteça. Isso torna os eventos assíncronsos por natureza, eliminando completamente o risco de correr através de intervalos.
Os eventos acontecem como resultado de uma ação, portanto não há sistema de destino; não podemos dizer que o serviço A desencadeia eventos para o serviço B; o que podemos dizer é que o serviço B está interessado nos eventos produzidos pelo serviço A. Mas pode haver algumas outras partes interessadas também, como o serviço C ou D.
Então, como podemos garantir que um evento desencadeado por um sistema atinja todos os serviços interessados? Na maioria das vezes esse problema é resolvido por corretores de mensagens. Um corretor nada mais é do que um aplicativo que atua como intermediário entre o gerador de eventos (o aplicativo que criou o evento) e o consumidor do evento. Dessa forma, os aplicativos são bem dissociados cuidando da questão da Disponibilidade que falei no início do post. Se um aplicativo não estiver disponível momentaneamente, quando ele voltar a funcionar, ele começará a consumir eventos e processá-los, atualizando-se com todos os eventos desencadeados quando o aplicativo estava desligado.
E quanto ao armazenamento? Os eventos podem ser armazenados em um banco de dados ou haverá algo mais no lugar? Os eventos podem definitivamente ser armazenados em bancos de dados, mas ao fazê-lo, eles perdem seu aspecto de "evento". Depois que um evento acontece, não podemos mudá-lo, então os eventos são imutáveis. Bancos de dados, por outro lado... eles são mutáveis, podemos realmente alterar dados depois que eles foram inseridos.
Uma melhor abordagem para armazenar eventos é usando registros de eventos. Os registros de eventos nada mais são do que um armazenamento centralizado de dados onde cada evento é armazenado como uma sequência de registros imutáveis, também chamado de log. Imagine o registro como um diário, onde cada novo evento é anexado ao final da lista. Podemos sempre recriar o estado mais recente reproduzindo todos os eventos desde o log desde o início até o presente.
A única parte que ainda não cobri é a escalabilidade. Os serviços construídos usando a mentalidade orientada a eventos foram projetados para serem implantados em um cenário de várias instâncias. Como o próprio Estado é armazenado no registro de eventos, o serviço em si será apátrida, o que permite o dimensionamento cirúrgico de qualquer serviço específico que quisermos.
A única exceção a esse padrão são os serviços que devem criar visões materializadas. Em essência, uma visão materializada representa o Estado em um ponto em tempo de um registro de eventos. Essa abordagem é usada para consultar os dados com mais facilidade. Voltando ao nosso problema de escalabilidade, a visão materializada nada mais é do que eventos agregados em uma tabela como formato, mas onde armazenamos essas tabelas? Na maioria das vezes, vemos essas agregações realizadas na memória, o que transforma automaticamente nosso serviço em um estado. Uma solução rápida e fácil é adicionar um banco de dados local a cada serviço que crie visualizações materializadas. Dessa forma, o Estado é armazenado no banco de dados e o serviço é mais uma vez apátrida.
Embora a arquitetura orientada a eventos exista há mais de 15 anos, só recentemente ela ganhou enorme popularidade, e há uma razão para isso. A maioria das empresas está passando por uma fase de"transformação d igital",e com isso, exigências malucas ocorrem. A complexidade desses requisitos força os engenheiros a adotar novas formas de projetar softwares, aqueles que incorrem em menos acoplamento entre serviços e menor sobrecarga de manutenção. O EDA é uma solução para esses problemas, mas não é o único. Além disso, você não deve esperar que tudo possa ser resolvido adotando o EDA. Alguns recursos ainda podem exigir a boa e velha APS de REST sincronia ou armazenar dados em um banco de dados relacional. Verifique o que é melhor para você e projete-o apropriadamente!
O Avance Network é uma comunidade fácil de usar que fornece segurança de primeira e não requer muito conhecimento técnico. Com uma conta, você pode proteger sua comunicação e seus dispositivos. O Avance Network não mantém registros de seus dados; portanto, você pode ter certeza de que tudo o que sai do seu dispositivo chega ao outro lado sem inspeção.