Identificando limites de microsserviço

Qual é o tamanho correto de um microsserviço? Muitas vezes você ouve algo como, "não muito grande e não muito pequeno" — e, embora isso seja correto, não é muito útil, na prática. Mas, se você iniciar de um modelo de domínio cuidadosamente desenvolvido, será mais fácil pensar sobre microsserviços.

Diagrama de contextos limitados

Este artigo usa um serviço de entrega drone como um exemplo em execução. Você pode ler mais sobre o cenário e a implementação de referência correspondente aqui.

Do modelo de domínio a microsserviços

No artigo anterior, definimos um conjunto de contextos limitados para um aplicativo de entrega drone. Então, analisamos mais de perto um desses contextos limitados, o contexto limitado de Envio, e identificamos um conjunto de entidades, agregados e serviços de domínio para esse contexto limitado.

Agora estamos prontos para passar do modelo de domínio para o design do aplicativo. Veja uma abordagem que você pode usar para derivar os microsserviços do modelo de domínio.

  1. Comece com um contexto limitado. Em geral, a funcionalidade em um microsserviço não deve abranger mais de um contexto limitado. Por definição, um contexto limitado marca o limite de um modelo de domínio específico. Se você achar que um microsserviço combina diferentes modelos de domínio, é sinal de que precisa voltar e refinar sua análise de domínio.

  2. Em seguida, examine os agregados no seu modelo de domínio. Agregados são, frequentemente, bons candidatos a microsserviços. Um agregado bem projetado exibe muitas das características de um microsserviço bem projetado, por exemplo:

    • Agregados são derivados de requisitos de negócios, e não de questões técnicas, como acesso a dados ou mensagens.
    • Uma agregação deve ter alta coesão funcional.
    • Uma agregação é um limite de persistência.
    • As agregações devem ser livremente acopladas.
  3. Serviços de domínio sempre são bons candidatos a microsserviços. Os serviços de domínio são operações sem estado em várias agregações. Um exemplo típico é um fluxo de trabalho que envolve vários microsserviços. Veremos um exemplo disso no aplicativo de Entrega por Drone.

  4. Por fim, considere os requisitos não funcionais. Observe fatores como tamanho da equipe, tipos de dados, tecnologias, requisitos de escalabilidade, requisitos de disponibilidade e requisitos de segurança. Esses fatores podem levá-lo a decompor ainda mais um microsserviço em dois ou mais serviços menores, ou fazer o contrário e combinar vários microsserviços em um.

Depois de identificar os microsserviços em seu aplicativo, valide o design conforme os seguintes critérios:

  • Cada serviço tem uma única responsabilidade.
  • Não há nenhuma chamada de conversa entre os serviços. Se a divisão da funcionalidade em dois serviços gerar excesso de conversas, isso poderá ser um sintoma de que essas funções pertencem ao mesmo serviço.
  • Cada serviço é pequeno o suficiente para ser criado por uma pequena equipe trabalhando de forma independente.
  • Não há nenhuma interdependência que exige que dois ou mais serviços sejam implantados em sincronia. Deve ser sempre possível implantar um serviço sem redistribuir outros serviços.
  • Os serviços não estão acoplados de forma firme e podem evoluir de forma independente.
  • Os limites do serviço não criarão problemas de consistência ou integridade de dados. Às vezes, é importante manter a consistência dos dados colocando a funcionalidade em um único microsserviço. Dito isto, considere se você realmente precisa de consistência forte. Existem estratégias para abordar a eventual consistência em um sistema distribuído, e os benefícios dos serviços de decomposição geralmente superam os desafios de gerenciar a consistência eventual.

Acima de tudo, é importante ser pragmático e lembrar-se de que o design orientado por domínio é um processo iterativo. Em caso de dúvida, comece com microsserviços de granulação grosseira. É mais fácil dividir um microsserviço em dois serviços menores do que refatorar a funcionalidade em vários microsserviços existentes.

Exemplo: definindo microservices para o aplicativo de entrega drone

Lembre-se de que a equipe de desenvolvimento identificou as quatro agregações — Entrega, Pacote, Drone e Conta — e dois serviços de domínio, Agendador e o Supervisor.

Entrega e Pacote são candidatos óbvios a microsserviços. O Agendador e o Supervisor coordenam as atividades executadas por outros microsserviços, então, faz sentido implementar esses serviços de domínio como microsserviços.

Drone e Conta são interessantes porque pertencem a outros contextos limitados. Uma opção é Agendador chamar contextos limitados de Drone e Conta diretamente. Outra opção é criar microsserviços de Drone e Conta dentro do contexto de envio limitado. Esses microsserviços fariam a mediação entre os contextos delimitados, expondo as APIs ou os esquemas de dados mais adequados ao contexto de Envio.

Os detalhes dos contextos limitados de Drone e Conta estão além do escopo desta orientação, portanto, criamos serviços fictícios para eles em nossa implementação de referência. Mas, aqui estão alguns fatores a considerar nessa situação:

  • Qual é a sobrecarga de rede ao chamar diretamente outro contexto limitado?

  • O esquema de dados para o outro contexto limitado é adequado para esse contexto ou é melhor ter um esquema adaptado a esse contexto limitado?

  • O outro contexto limitado é sistema herdado? Em caso afirmativo, crie um serviço que atue como camada anticorrupção para converter entre o sistema herdado e o aplicativo moderno.

  • O que é a estrutura de equipe? É fácil se comunicar com a equipe responsável pelo outro contexto limitado? Se não for fácil, a criação de um serviço que faça a mediação entre os dois contextos pode ajudar a atenuar o custo da comunicação entre equipes.

Até agora, não consideramos nenhum requisito não funcional. Pensando nos requisitos de taxa de transferência do aplicativo, a equipe de desenvolvimento decidiu criar um microsserviço de Ingestão separado, responsável pela ingestão de solicitações do cliente. Esse microsserviço implementará o nivelamento de carga, colocando as solicitações recebidas em um buffer para processamento. O Agendador fará a leitura das solicitações do buffer e executará o fluxo de trabalho.

Requisitos não funcionais levaram a equipe a criar um serviço adicional. Todos os serviços até agora foram sobre o processo de agendamento e entrega de pacotes em tempo real. Mas o sistema também precisa armazenar o histórico de cada entrega no armazenamento de longo prazo para análise dos dados. A equipe considerou atribuir essa responsabilidade ao serviço de Entrega. No entanto, os requisitos de armazenamento de dados são muito diferentes para a análise histórica versus operações em andamento (consulte Considerações sobre dados). Portanto, a equipe decidiu criar um serviço de Histórico de Entrega separado, que escutará eventos DeliveryTracking do serviço de Entrega e gravará os eventos no armazenamento de longo prazo.

O diagrama a seguir mostra o design neste ponto:

Diagrama de design

Próximas etapas

Neste ponto, você deve ter uma compreensão clara da finalidade e da funcionalidade de cada microserviço em seu design. Agora você pode arquitetar o sistema.