Como ajustar um mecanismo de regras em uma arquitetura de microsserviço quando ele requer muitos dados de entrada?


12

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-cartmicrosserviç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-cartmodo 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

  1. Deixe o mecanismo de regras buscar os dados necessários. Isso acrescentaria ainda mais complexidade, violando o princípio da responsabilidade única ( ainda mais ... );
  2. Implemente um proxy μs antes do mecanismo de regras para buscar os dados;
  3. Implemente um "buscador de dados" que o mecanismo de regras chama para buscar todos os dados necessários de uma só vez (consulta composta).

Deixe-me resumir (com perguntas): você tem vários microsserviços implementados para uma loja. Um deles é um carrinho de compras . Incorporado ao carrinho está um mecanismo de regras (homebrew ou algum produto), certo? Quando um usuário adiciona um item ao carrinho, o mecanismo de regras entra em ação como parte da lógica de negócios e modifica o carrinho de alguma forma (por exemplo, produtos com desconto ou pacote), certo? Agora, outro microsserviço também deseja usar regras que podem ser baseadas em dados de entrada semelhantes, certo? E os dados de entrada são fornecidos por outros microsserviços, certo? Por que a busca de dados é tão complexa?
Andy

3
Sua melhor aposta para evitar esses problemas é se livrar do mecanismo de regras.
Whatsisname

@ Andy O mecanismo de regras é um microsserviço separado. Sua API é um pouco adaptada 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.
Didier L

@whatsisname Eu não sou muito fã de ter um mecanismo de regras em geral, mas no momento atual temos que lidar com isso e assim mesmo, e a empresa está mudando sua configuração no dia-a-dia. Mesmo se nos livrarmos dele, ainda precisaríamos de algum componente configurável para fazer as mesmas coisas, exigindo os mesmos dados de entrada ... Ainda seria um mecanismo de regras, apenas com outro nome, e ainda enfrentaríamos os mesmos problemas.
Didier L

Respostas:


8

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:

  • Um grande monólito (o mecanismo de regras)
  • Uma grande quantidade de dados não modularizados que são enviados em massa
  • É difícil obter dados de e para o mecanismo de regras
  • Você não pode remover o mecanismo de regras

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.

todos (chamando o mecanismo de regras) precisam reimplementar a busca dos dados, mesmo que não precisem deles;

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.

as solicitações para o mecanismo de regras são complexas;

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.

Também devemos garantir que não se torne um gargalo - por exemplo, alguns dados demoram a ser buscados (10s ou mais)

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.


Obrigado pela sua resposta, @enderland. De fato, a arquitetura de microsserviços ainda é relativamente nova para nós, daí esta questão. Esse mecanismo de regras evoluiu um pouco organicamente para nos levar até aqui, por isso agora precisamos de instruções de direção para corrigi-lo. É (felizmente) completamente sem estado, portanto, a quantidade de dados que ele recebe como entrada. E é isso que gostaríamos de abordar primeiro para torná-lo um componente reutilizável. Mas como reduzir a quantidade de dados de entrada sem reduzir o número de predicados disponíveis? Eu acho que precisamos de uma API capaz de buscar os dados por conta própria, mas como arquitetá-los corretamente?
Didier L

Com relação aos problemas de desempenho, esses provêm de microsserviços que estão realmente chamando serviços JMS e SOAP lentos implementados por back-ends. Eles têm seus próprios bancos de dados, mas o desempenho não é realmente seu primeiro objetivo (desde que lide com a carga). E há muitos deles para considerar replicar seus dados e mantê-los (para alguns, porém). O melhor que podemos fazer é fazer cache e pré-buscar.
Didier L

Então, quando você menciona " alguns mecanismos de regras ", entendo que você quer dizer mecanismos de regras especializados que avaliam apenas predicados com um tipo de entrada, certo? Você sugeriria que eles buscassem os dados de que precisam ou deveriam ser buscados antecipadamente? Também precisaríamos de algum componente para orquestrar a combinação de predicados, certo? E preste atenção para não adicionar muita sobrecarga de rede devido a essa orquestração.
Didier L

1

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.


0

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.


0

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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.