Situação atual
Estamos implementando (e agora mantendo) um aplicativo Web de compras on-line em uma arquitetura de microsserviço.
Um dos requisitos é que a empresa possa aplicar regras sobre o que nossos clientes adicionam ao carrinho, para personalizar sua experiência e o pedido final. Obviamente, um mecanismo de regras de negócios precisou ser implementado e implementamos um "microsserviço" específico para isso (se ainda pudéssemos chamá-lo).
Ao longo de um ano, esse mecanismo de regras tornou-se cada vez mais complexo, exigindo mais e mais dados (por exemplo, conteúdo do carrinho, mas também informações do usuário, sua função, seus serviços existentes, algumas informações de cobrança etc.) para poder calcular essas regras.
No momento, nosso shopping-cart
microsserviço está coletando todos esses dados de outros microsserviços. Embora parte desses dados seja usada por shopping-cart
, na maioria das vezes, é usada principalmente para alimentar o mecanismo de regras.
Novos requisitos
Agora chega a necessidade de outros aplicativos / microsserviços reutilizarem o mecanismo de regras para requisitos semelhantes. Na situação atual, eles teriam que transmitir o mesmo tipo de dados, chamar os mesmos microsserviços e criar (quase) os mesmos recursos para poder chamar o mecanismo de regras.
Continuando como está, enfrentaremos vários problemas:
- todos (chamando o mecanismo de regras) precisam reimplementar a busca dos dados, mesmo que não precisem deles;
- as solicitações para o mecanismo de regras são complexas;
- continuando nessa direção, teremos que transportar esses dados por toda a rede para muitas solicitações (pense em μs A chamando μs B chamando o mecanismo de regras, mas A já possui alguns dos dados que o mecanismo de regras precisa);
shopping-cart
tornou-se enorme devido a toda a busca de dados;- Eu provavelmente esqueço muitos ...
O que podemos fazer para evitar esses problemas?
Idealmente, evitaríamos adicionar mais complexidade ao mecanismo de regras. Também devemos garantir que ele não se torne um gargalo - por exemplo, alguns dados demoram a ser buscados (10s ou mais), por isso implementamos a pré-busca, de shopping-cart
modo que é mais provável que os dados existam antes de chamarmos as regras mecanismo e mantenha uma experiência aceitável do usuário.
Algumas ideias
- Deixe o mecanismo de regras buscar os dados necessários. Isso acrescentaria ainda mais complexidade, violando o princípio da responsabilidade única ( ainda mais ... );
- Implemente um proxy μs antes do mecanismo de regras para buscar os dados;
- Implemente um "buscador de dados" que o mecanismo de regras chama para buscar todos os dados necessários de uma só vez (consulta composta).
shopping-cart
, mas podemos adaptá-la facilmente às necessidades de outros microsserviços (eles ainda estão relacionados a usuários, produtos e pedidos). A nosso ver, eles vão precisar dos mesmos dados de entrada, especialmente porque a empresa é capaz de escolher os predicados para aplicar. Todos os dados são fornecidos por outros microsserviços, exceto o próprio conteúdo do carrinho. A busca dos dados não é complexa por si só, mas se torna complexa quando você precisa chamar ~ 10 outros microsserviços e manter a estrutura esperada pelo mecanismo de regras.Respostas:
Vamos dar um passo para trás por um segundo e avaliar nosso ponto de partida antes de escrever essa resposta que provavelmente será nova. Você tem:
Ok, isso não é ótimo para microsserviços. Um problema imediatamente flagrante é que vocês parecem estar entendendo mal o que são microsserviços.
Você precisa definir algum tipo de API ou método de comunicação que seus microsserviços usam e que seja comum. Pode ser uma biblioteca que todos eles podem importar. Pode estar definindo um protocolo de mensagens. Pode estar usando uma ferramenta existente ( procure barramentos de mensagens de microsserviço como um bom ponto de partida).
A questão da comunicação entre serviços não é um problema "resolvido" por si só, mas também não é um problema do tipo "faça você mesmo" neste momento. Muitas ferramentas e estratégias existentes podem facilitar sua vida.
Independentemente do que você faz, escolha um único sistema e tente adaptar suas APIs de comunicação para usar isso. Sem uma maneira definida de interagir com seus serviços, você terá todas as desvantagens de microsserviços e serviços monolíticos e nenhuma das vantagens de ambos.
A maioria dos seus problemas decorre disso.
Torne-os menos complexos.
Encontre maneiras de torná-los menos complexos. Seriamente. Modelos de dados comuns, dividem seu mecanismo de regras único em outros menores ou algo assim. Faça seu mecanismo de regras funcionar melhor. Não adote a abordagem "conecte tudo na consulta e apenas continue complicando" - observe seriamente o que você está fazendo e por quê.
Defina algum tipo de protocolo para seus dados. Meu palpite é que vocês não têm um plano de API definido (conforme descrito acima) e começaram a escrever chamadas REST ad hoc sempre que necessário. Isso fica cada vez mais complexo, pois agora você precisa manter todos os microsserviços sempre que algo for atualizado.
Melhor ainda, você não é exatamente a primeira empresa a implementar uma ferramenta de compras online. Vá pesquisar outras empresas.
O que agora...
Depois disso, você pelo menos alterou alguns dos maiores problemas.
A próxima questão é essa questão do seu mecanismo de regras. Espero que isso seja razoavelmente sem estado, para que você possa escalá-lo. Se for, enquanto abaixo do ideal, você pelo menos não vai morrer em um incêndio de glória ou criar soluções insanas.
Você deseja que seu mecanismo de regras seja sem estado. Faça com que processe apenas dados. Se você o encontrar como gargalo, faça com que seja possível executar vários atrás de um proxy / balanceador de carga. Não é o ideal, mas ainda é viável.
Passe algum tempo considerando se algum dos seus microsserviços realmente deve ser colocado no mecanismo de regras. Se você está aumentando a sobrecarga do sistema de maneira tão significativa apenas para obter uma "arquitetura de microsserviços", precisa gastar mais tempo planejando isso.
Como alternativa, seu mecanismo de regras pode ser dividido em pedaços? Você pode obter ganhos apenas criando partes de seus serviços específicos do mecanismo de regras.
Supondo que esse problema exista após a solução dos problemas acima, você precisará investigar seriamente por que isso está acontecendo. Você tem um pesadelo se desenrolando, mas em vez de descobrir por que (10 segundos? Para enviar dados do portal de compras ? Me chame de cínico, mas isso parece um pouco absurdo), você parece estar corrigindo os sintomas em vez de olhar para o problema que os causa. o primeiro lugar.
Você usou a frase "busca de dados" repetidamente. Esses dados estão em um banco de dados? Caso contrário, considere fazer isso - se você estiver gastando tanto tempo "manualmente" buscando dados, parece que usar um banco de dados real seria uma boa idéia.
Você pode ter um design com um banco de dados para os dados que você busca (dependendo do que é isso, você mencionou várias vezes), alguns mecanismos de regras e seu (s) cliente (s).
Uma última observação é que você deseja garantir o uso de versão adequada de suas APIs e serviços. Uma versão secundária não deve prejudicar a compatibilidade com versões anteriores. Se você estiver lançando todos os seus serviços ao mesmo tempo para que funcionem, não possui uma arquitetura de microsserviço, possui uma arquitetura monolítica distribuída.
E, finalmente, os microsserviços não são uma solução única para todos. Por favor, pelo bem de tudo que é sagrado, não faça isso apenas porque é a coisa nova da moda.
fonte
Com a quantidade de informações apresentadas sobre o mecanismo de regras e suas entradas e saídas, acho que sua sugestão não. 2 está no caminho certo.
Os consumidores atuais do mecanismo de regras podem terceirizar o processo de coleta das informações necessárias para um componente de finalidade mais especial.
Exemplo: no momento, você está usando o mecanismo de regras para calcular descontos que precisam ser aplicados ao conteúdo do carrinho de compras. Compras anteriores, geografia e ofertas atuais são um fator importante.
O novo requisito é usar muitas dessas informações para enviar ofertas por e-mail a clientes anteriores com base nas próximas promoções e compras anteriores. Compras anteriores, ofertas atuais e futuras são um fator importante.
Eu teria dois serviços separados para isso. Cada um deles confiaria no serviço de mecanismo de regras para parte de seu trabalho pesado. Cada um deles coletaria os dados necessários para sua solicitação ao mecanismo de regras.
O mecanismo de regras apenas aplica as regras, os consumidores não precisam se preocupar com os dados exatos que o mecanismo de regras precisa para o contexto específico, e esses novos serviços intermediários fazem apenas uma coisa: montar o contexto e transmitir a solicitação ao mecanismo de regras e retorna a resposta sem modificação.
fonte
A agregação dos dados necessários para a decisão deve ser feita fora do mecanismo de regras. Isso ocorre porque eles são melhor projetados como serviços sem estado, quando possível. A busca de dados envolve necessariamente processamento assíncrono e retenção de estado. Não importa muito se a busca é feita por um proxy na frente do serviço de decisão, pelos chamadores ou por um processo de negócios.
Como uma questão prática para implementação, mencionarei que o IBM Operational Decision Manager está começando a documentar e já suporta o uso do produto em contêineres de docker . Estou certo de que outros produtos também fornecem esse suporte e que ele se tornará popular.
fonte
Na minha opinião, acho que ajudará a pré-buscar todos os dados necessários, fazendo um conjunto de chamadas assíncronas para serviços de recuperação de dados assim que o cliente começar a comprar e armazenar em cache os dados. Portanto, quando você precisar chamar o serviço de regras, os dados já estarão lá. E continue disponível para outros serviços também durante a sessão.
fonte