Meu cenário é o seguinte.
Estou projetando um sistema projetado para receber dados de vários tipos de sensores, converter e depois persistir para que ele seja usado por vários serviços de análise e front-end posteriormente.
Estou tentando projetar cada serviço para ser o mais independente possível, mas estou tendo alguns problemas. A equipe decidiu um DTO que gostaríamos de usar. Os serviços voltados para o exterior (destinatários de dados do sensor) receberão os dados de maneira exclusiva e depois os converterão em um objeto JSON (o DTO) e os enviarão para o Message Broker. Os consumidores das mensagens saberão exatamente como ler as mensagens de dados do sensor.
O problema é que estou usando o mesmo DTO em alguns serviços diferentes. Uma atualização deve ser implementada em vários locais. Obviamente, nós o projetamos de tal maneira que alguns campos extras ou ausentes no DTO aqui e não há muito problema até que os serviços sejam atualizados, mas ele ainda está me incomodando e me faz sentir como se estivesse Cometer um erro. Poderia facilmente se transformar em dor de cabeça.
Estou arquitetando o sistema errado? Se não, quais são algumas maneiras de contornar isso, ou pelo menos para aliviar minhas preocupações?
proto
arquivo para gRPC ou oavro
esquema para Kafka e gerar os DTOs nos dois serviços, mas eu não compartilharia uma biblioteca compartilhada entre dois projetos.Respostas:
Meu conselho? Não compartilhe esses DTOs entre os aplicativos em qualquer tipo de biblioteca. Ou pelo menos não faça isso agora.
Eu sei, parece muito contra-intuitivo. Você está duplicando código, certo? Mas essa não é uma regra comercial, portanto você pode ser mais flexível.
O serviço que envia o DTO precisa ser rígido em seu contrato de mensagens, como uma API Rest. O serviço não pode alterar o DTO de maneira que possa interromper os outros serviços que já estão consumindo as informações do DTO.
Quando um novo campo é adicionado ao DTO, você atualiza apenas os outros serviços que consomem esse DTO se eles precisarem do novo campo. Caso contrário, esqueça. Usando JSON como tipo de conteúdo, você tem a flexibilidade de criar e enviar novos atributos sem interromper o código dos serviços que não mapeiam esses novos campos em suas versões reais do DTO.
Mas se essa situação realmente o estiver incomodando, você pode seguir a Regra dos Três :
Portanto, tente esperar um pouco mais antes de compartilhar este DTO entre os serviços.
fonte
Quando se trata de microsserviços, os ciclos de vida de desenvolvimento dos serviços também devem ser independentes. *
SLDC diferentes e diferentes equipes de desenvolvimento
em um sistema real de EM, pode haver várias equipes envolvidas no desenvolvimento do ecossistema, cada uma delas encarregada de um ou mais serviços. Por sua vez, essas equipes podem estar localizadas em escritórios, cidades, países, planos ... Talvez eles nem se conheçam, o que dificulta o compartilhamento de conhecimento ou código (se possível). Mas isso pode ser muito conveniente, porque o código compartilhado também implica um tipo de raciocínio de compartilhamento e algo importante a lembrar é que, o que faz sentido para uma equipe específica, não precisa ser para outra equipe. Por exemplo, dado o Cliente do DTO , ele pode ser diferente dependendo do serviço em execução, porque os clientes são interpretados (ou vistos) de maneira diferente de cada serviço.
Necessidades diferentes, tecnologias diferentes
SLDCs isolados também permitem que as equipes escolham a pilha que melhor se adapta às suas necessidades. A imposição de DTOs implementados em uma tecnologia específica limita a capacidade das equipes de escolher.
DTOs não são regras de negócios nem contratos de serviços
O que os DTOs são realmente? Objetos simples com nenhum outro objetivo além de mover dados de um lado para outro. Sacos de caçadores e caçadores. Não é o tipo de "conhecimento" que vale a pena reutilizar, em geral porque não há conhecimento. Sua volatilidade também os torna maus candidatos ao acoplamento.
Ao contrário do que a Dherik declarou, deve ser possível que um serviço altere seus DTOs sem precisar fazer outros serviços para alterar ao mesmo tempo. Os serviços devem ser leitores tolerantes, escritores tolerantes e tolerantes a falhas . Caso contrário, eles causam acoplamentos de forma que a arquitetura de serviço não faz sentido. Mais uma vez, e ao contrário da resposta de Dherik, se três serviços precisarem exatamente dos mesmos DTOs, é provável que algo tenha dado errado durante a decomposição dos serviços.
Negócios diferentes, interpretações diferentes
Embora possa haver (e haverá) conceitos transversais entre os serviços, isso não significa que devemos impor um modelo canônico para forçar todos os serviços a interpretá-los da mesma maneira.
Estudo de caso
Digamos que nossa empresa tenha três departamentos, Atendimento ao Cliente , Vendas e Remessa . Diga a cada um desses lançamentos um ou mais serviços.
O Atendimento ao Cliente, devido ao seu idioma de domínio , implementa serviços em torno do conceito de clientes, onde os clientes são pessoas . Por exemplo, os clientes são modelados como nome , sobrenome , idade , sexo , email , telefone etc.
Agora, digamos, Vendas e Remessa modelam seus serviços de acordo com os respectivos idiomas de domínio. Nesses idiomas, o conceito de cliente também aparece, mas com uma diferença sutil. Para eles, os clientes não são (necessariamente) pessoas . Para vendas , os clientes são um número de documento de um cartão de crédito e um endereço de cobrança , para transporte de um nome completo e endereço de entrega também.
Se forçarmos o Sales and Shipping a adotar o modelo de dados canônicos do Atendimento ao Cliente , os forçaremos a lidar com dados desnecessários que podem acabar introduzindo complexidade desnecessária se eles tiverem que manter toda a representação e manter os dados do cliente sincronizados com o atendimento ao cliente .
Links Relacionados
* Aqui é onde estão os pontos fortes dessa arquitetura
fonte
Você deve publicar eventos . Eventos são certos tipos de mensagens que representam um fato sólido sobre algo que aconteceu em um determinado momento.
Cada serviço deve ter uma responsabilidade muito bem definida e deve ter a responsabilidade de publicar os eventos relacionados a essa responsabilidade.
Além disso, você deseja que seus eventos representem eventos relacionados a negócios, não eventos técnicos. Por exemplo, prefira
OrderCancelled
evento a umOrderUpdated
comstatus: "CANCELLED"
.Dessa forma, quando um serviço precisa reagir a um pedido cancelado, ele precisa apenas ouvir esse tipo específico de mensagem, que carrega apenas dados relevantes para esse evento. Por exemplo, um
OrderCancelled
provavelmente só precisa de umorder_id
. Qualquer serviço que precise reagir a isso já armazenou o que precisa saber sobre o pedido em seu próprio armazenamento de dados.Mas se o serviço tivesse apenas
OrderUpdated
eventos para ouvir, seria necessário interpretar o fluxo de eventos e agora dependia da ordem de entrega concluir corretamente quando um pedido era cancelado.No seu caso, no entanto, como você está publicando dados do sensor, pode fazer sentido ter um serviço, ouvir os eventos e publicar um novo fluxo de "eventos de negócios", por exemplo
TemperatureThresholdExceeded
,TemperatureStabilised
.E tenha cuidado ao criar muitos microsserviços. Os microsserviços podem ser uma ótima maneira de encapsular a complexidade, mas se você não descobrir limites de serviço adequados, sua complexidade estará na integração de serviços. E isso é um pesadelo para manter.
É melhor ter poucos serviços grandes demais do que ter muitos serviços pequenos demais.
fonte