Dicotomia de dados: repensando a relação com dados e serviços

Olá a todos! Temos ótimas notícias. Em junho, a OTUS inicia o curso “Arquiteto de Software” novamente e, portanto, tradicionalmente compartilhamos material útil com você.




Se você se deparar com toda essa história com microsserviços sem nenhum contexto, poderá desculpar-se por considerá-la um pouco estranha. Particularmente, particionar o aplicativo em fragmentos conectados por uma rede significa adicionar modos complexos de tolerância a falhas ao sistema distribuído resultante.

Apesar de essa abordagem incluir a divisão em muitos serviços independentes, o objetivo final é muito mais do que apenas a operação desses serviços em máquinas diferentes. Estamos falando de interação com o mundo exterior, que em sua essência também é distribuído. Não no sentido técnico, mas no sentido de um ecossistema que consiste em muitas pessoas, equipes, programas e cada uma dessas partes deve, de alguma forma, fazer seu trabalho.

As empresas, por exemplo, são um conjunto de sistemas distribuídos que, juntos, contribuem para a consecução de um determinado objetivo. Ignoramos esse fato há décadas, tentando obter a unificação, a transferência de arquivos via FTP ou o uso de ferramentas de integração corporativa, enquanto nos concentramos em nossos objetivos pessoais isolados. Mas com o advento dos serviços, tudo mudou. Os serviços nos ajudaram a olhar além do horizonte e a ver o mundo dos programas interdependentes que trabalham juntos. No entanto, para trabalhar com sucesso, é necessário realizar e projetar dois mundos fundamentalmente diferentes: o mundo exterior, onde vivemos em um ecossistema de muitos outros serviços, e o nosso mundo pessoal e interno, onde governamos sozinhos.



Um mundo assim distribuído é diferente daquele em que crescemos e com o qual estamos acostumados. Os princípios da construção da arquitetura monolítica tradicional não resistem às críticas. Portanto, um entendimento correto desses sistemas é mais do que criar um diagrama de sala de aula em um quadro branco ou uma prova legal de conceito. É sobre esse sistema funcionando com sucesso por um longo tempo. Felizmente, os serviços existem há algum tempo, embora pareçam diferentes. As lições de SOA ainda são relevantes, mesmo com sabor de Docker, Kubernetes e barbas hipster um pouco maltratadas.

Então, hoje analisamos como as regras mudaram, por que precisamos repensar nossa abordagem dos serviços e dados que eles transmitem uns aos outros e por que precisamos de ferramentas completamente diferentes para isso.

O encapsulamento nem sempre será seu amigo


Os microsserviços podem funcionar independentemente um do outro. É essa propriedade que lhes dá o maior valor. A mesma propriedade permite que os serviços aumentem e cresçam. Não tanto em termos de redução para quatrilhão de usuários ou petabytes de dados (embora aqui possam ajudar), mas em termos de escala do ponto de vista das pessoas, porque equipes e organizações estão crescendo continuamente.



No entanto, a independência é uma faca de dois gumes. Ou seja, o próprio serviço pode girar com facilidade e naturalidade. Mas se uma função é implementada dentro do serviço que requer o uso de outro serviço, no final, temos que fazer alterações nos dois serviços quase simultaneamente. No monólito, isso é fácil, basta fazer uma alteração e enviá-la para o lançamento, mas no caso da sincronização de serviços independentes, haverá mais problemas. A coordenação entre equipes e ciclos de lançamento destrói a flexibilidade.



Como parte da abordagem padrão, mudanças irritantes de ponta a ponta são simplesmente evitadas, dividindo claramente a funcionalidade entre os serviços. O serviço de logon único aqui pode ser um bom exemplo. Ele tem um papel claramente definido que o distingue de outros serviços. Uma separação tão clara significa que, em um mundo de requisitos que mudam rapidamente para os serviços que o cercam, é improvável que o serviço de logon único seja alterado. Existe dentro de um contexto estritamente limitado.



O problema é que, no mundo real, os serviços de negócios não podem manter constantemente uma separação de papéis igualmente limpa. Por exemplo, os mesmos serviços de negócios trabalham mais com dados provenientes de outros serviços semelhantes. Se você estiver envolvido no varejo on-line, o processamento do fluxo de pedidos, do catálogo de produtos ou das informações do usuário se tornará um requisito para muitos de seus serviços. Cada um dos serviços precisará acessar esses dados para funcionar.


A maioria dos serviços de negócios usa o mesmo fluxo de dados, portanto, seu trabalho está sempre entrelaçado.

Então chegamos a um ponto importante sobre o qual vale a pena falar. Embora os serviços funcionem bem para componentes de infraestrutura que funcionam em grande parte separados, a maioria dos serviços de negócios está mais interligada.

Dicotomia de dados


As abordagens orientadas a serviços podem já existir, mas elas ainda têm poucas informações sobre como trocar grandes quantidades de dados entre serviços.

O principal problema é que dados e serviços são inseparáveis. Por um lado, o encapsulamento nos encoraja a ocultar dados para que os serviços possam ser separados um do outro e facilitar seu crescimento e outras alterações. Por outro lado, precisamos ser capazes de compartilhar e dominar livremente dados gerais, bem como quaisquer outros. Trata-se de poder iniciar imediatamente o trabalho, tão livremente quanto em qualquer outro sistema de informação.

No entanto, sistemas de informação têm pouco a ver com encapsulamento. De fato, mesmo o oposto. Os bancos de dados fazem tudo o que podem para dar acesso aos dados armazenados neles. Eles vêm com uma poderosa interface declarativa que permite modificar os dados conforme necessário. Essa funcionalidade é importante no estágio da pesquisa preliminar, mas não para gerenciar a crescente complexidade de um serviço em constante evolução.



E aqui surge um dilema. Contradição. Dicotomia. Afinal, os sistemas de informação são sobre o fornecimento de dados e os serviços são sobre a ocultação.

Essas duas forças são fundamentais. Eles formam a base da maior parte do nosso trabalho, buscando constantemente a excelência nos sistemas que criamos.

À medida que os sistemas de serviço crescem e evoluem, vemos diferentes manifestações dos efeitos da dicotomia de dados. Ou a interface de serviço aumentará, fornecendo uma gama cada vez maior de funções e começará a parecer um banco de dados doméstico muito maravilhoso, ou ficaremos desapontados e implementaremos uma maneira de extrair ou mover conjuntos de dados maciços inteiros de serviço para serviço.



Por sua vez, criar algo que se parece com um maravilhoso banco de dados doméstico levará a vários problemas. Não entraremos em detalhes sobre o perigo de um banco de dados compartilhado , apenas diga que ele representa dificuldades significativas de engenharia e operacionais caras para uma empresa que está tentando usá-lo.

Pior, os volumes de dados multiplicam os problemas com os limites de serviço. Quanto mais dados comuns estiverem dentro do serviço, mais complicada será a interface e mais difícil será combinar os conjuntos de dados provenientes de diferentes serviços.

Uma abordagem alternativa para extrair e mover conjuntos de dados inteiros também tem seus problemas. Uma abordagem comum para esse problema parece uma simples recuperação e armazenamento de todo o conjunto de dados e, em seguida, armazená-lo localmente em cada serviço ao consumidor.



O problema é que serviços diferentes interpretam os dados que eles consomem de maneira diferente. Esses dados estão sempre à mão. Eles são modificados e processados ​​localmente. Muito rapidamente, eles deixam de ter algo em comum com os dados na fonte.


Quanto mais mutáveis ​​as cópias, mais os dados variam com o tempo.

Pior ainda, é difícil corrigir esses dados em retrospecto (o MDM pode realmente ser útil aqui). De fato, alguns dos problemas tecnológicos intratáveis ​​que uma empresa enfrenta se devem à multiplicação de dados heterogêneos de aplicativo para aplicativo.

Para encontrar uma solução para esse problema sobre dados compartilhados, você precisa pensar de maneira diferente. Eles devem se tornar objetos de primeira classe nas arquiteturas que construímos. Pat hellandchama esses dados de "externos", e esse é um recurso muito importante. Precisamos de encapsulamento para não expor a estrutura interna do serviço, mas precisamos facilitar o acesso dos serviços a dados compartilhados para que eles possam executar corretamente seu trabalho.



O problema é que nenhuma das abordagens é relevante hoje, porque nem as interfaces de serviço, nem as mensagens, nem o Banco de Dados Compartilhado oferecem uma boa solução para trabalhar com dados externos. As interfaces de serviço são inadequadas para a troca de dados em qualquer escala. As mensagens movem os dados, mas não armazenam seu histórico; portanto, os dados são corrompidos ao longo do tempo. Os bancos de dados compartilhados se concentram demais em um ponto, que impede o progresso. Estamos inevitavelmente presos em um ciclo de falha de dados:


Ciclo de insolvência de dados

Streams: uma abordagem descentralizada de dados e serviços


Idealmente, precisamos mudar a abordagem de como os serviços funcionam com dados compartilhados. No momento, qualquer abordagem é confrontada com a dicotomia acima mencionada, uma vez que não há pólen mágico que possa ser generosamente borrifado com ele e feito para que ele desapareça. No entanto, podemos repensar o problema e chegar a um compromisso.

Esse compromisso envolve um certo grau de centralização. Podemos usar o mecanismo de log distribuído porque ele fornece fluxos escaláveis ​​confiáveis. Agora precisamos de serviços para poder ingressar e trabalhar com esses encadeamentos comuns, mas queremos evitar os complexos Serviços de Deus centralizados que executam esse processamento. Portanto, a melhor opção é incorporar o processamento de streaming em cada serviço ao consumidor. Portanto, os serviços poderão combinar conjuntos de dados de diferentes fontes e trabalhar com eles conforme necessário.

Uma maneira de conseguir essa abordagem é usar uma plataforma de streaming. Existem muitas opções, mas hoje consideraremos o Kafka, pois o uso de seu Stateful Stream Processing nos permite resolver efetivamente o problema apresentado.



O uso do mecanismo de log distribuído nos permite seguir um caminho bem trilhado e usar o sistema de mensagens para trabalhar com a arquitetura orientada a eventos . Acredita-se que essa abordagem forneça melhor escala e separação do que o mecanismo de solicitação-resposta, porque fornece controle do fluxo ao receptor, não ao remetente. No entanto, você tem que pagar por tudo nesta vida, e aqui você precisa de um corretor. Mas para sistemas grandes, essa troca vale a pena (o que não pode ser dito sobre seus aplicativos Web comuns).

Se um intermediário for responsável pelo log distribuído, e não por um sistema de mensagens tradicional, você poderá aproveitar os recursos adicionais. O transporte pode ser dimensionado linearmente quase como um sistema de arquivos distribuído. Os dados podem ser armazenados nos logs por um longo período de tempo, para obtermos não apenas mensagens, mas também armazenamento de informações. Armazenamento escalável sem medo de um estado geral mutável.

Em seguida, você pode usar o mecanismo de processamento de fluxo com estado para adicionar ferramentas de banco de dados declarativas aos serviços do consumidor. Este é um ponto muito importante. Enquanto os dados são armazenados em fluxos compartilhados que todos os serviços podem acessar, o pool e o processamento que o serviço faz são privados. Eles se vêem isolados dentro de um contexto estritamente limitado.


Livre-se da dicotomia de dados dividindo o fluxo imunológico dos estados. Em seguida, adicione esse recurso a cada serviço usando o Stateful Stream Processing.

Assim, se o seu serviço precisar trabalhar com pedidos, um catálogo de produtos, um armazém, ele terá acesso total: somente você decidirá quais dados combinar, onde processá-los e como devem ser alterados ao longo do tempo. Apesar de os dados serem gerais, o trabalho com eles é completamente descentralizado. É feito dentro de cada serviço, em um mundo onde tudo corre de acordo com suas regras.


Compartilhe dados para que sua integridade não seja violada. Encapsula uma função, não uma fonte, em todos os serviços que precisam.

Acontece que os dados precisam ser massivamente movidos. Às vezes, um serviço requer um conjunto de dados históricos locais em um mecanismo de banco de dados selecionado. O truque é que você pode garantir que, se necessário, uma cópia possa ser restaurada da fonte acessando o mecanismo de log distribuído. Os conectores da Kafka fazem um ótimo trabalho nisso.

Portanto, a abordagem considerada hoje tem várias vantagens:

  • Os dados são usados ​​na forma de fluxos compartilhados que podem ser armazenados por um longo tempo nos logs, e o mecanismo para trabalhar com dados compartilhados é conectado em cada contexto individual, o que permite que os serviços trabalhem de maneira rápida e fácil. Dessa forma, você pode equilibrar a dicotomia dos dados.
  • , , . .
  • Stateful Stream Processing , , .
  • , , , -.
  • , . , .
  • , .

Como você pode ver, isso é mais do que apenas REST. Temos um conjunto de ferramentas que permitem trabalhar com dados compartilhados de maneira descentralizada.

No artigo de hoje, nem todos os aspectos foram divulgados. Ainda precisamos decidir como equilibrar entre o paradigma solicitação-resposta e o paradigma orientado a eventos. Mas vamos lidar com isso na próxima vez. Há tópicos que você precisa conhecer melhor, por exemplo, por que o Processamento de Fluxo Stateful é tão bom. Falaremos sobre isso no terceiro artigo. E existem outros projetos poderosos que podemos usar se recorrermos a eles, por exemplo, Exatamente uma vez em processamento . Com sua ajuda, as regras do jogo para sistemas de negócios distribuídos são alteradas, pois esse design fornece garantias transacionais para o XAem forma escalável. Isso será discutido no quarto artigo. Finalmente, precisaremos revisar os detalhes da implementação desses princípios.



Mas, por enquanto, lembre-se do seguinte: uma dicotomia de dados é a força que enfrentamos ao criar serviços de negócios. E devemos lembrar disso. O truque é virar tudo de cabeça para baixo e começar a considerar os dados gerais como objetos de primeira classe. O Stateful Stream Processing fornece um compromisso exclusivo para isso. Ele evita os “Deus Componentes” centralizados, impedindo o progresso. Além disso, fornece a velocidade, escalabilidade e tolerância a falhas dos pipelines de fluxo de dados e os adiciona a cada serviço. Portanto, podemos nos concentrar no fluxo geral de consciência, ao qual qualquer serviço pode se conectar e trabalhar com seus dados. Portanto, os serviços são mais escaláveis, intercambiáveis ​​e autônomos. Portanto, eles não apenas ficarão bem nos quadros brancos e, ao testar hipóteses,mas também trabalhe e desenvolva por décadas.



.



All Articles