Como você projeta seu software que atualiza vários microsserviços, se um deles falhar?
Existe um padrão ou prática de design que eu possa usar para ajudar com serviços que estão inativos ou inativos, enquanto outros são estáveis?
E se eu tiver três microsserviços, e dois deles forem bons, e um morrer no meio de um POST? Dois receberão o POST e um não. Acho que não posso fazer transações porque estou enviando minhas solicitações para um serviço.
Como faço para projetar isso? Não quero dados órfãos em vários bancos de dados.
Não é um problema simples de resolver. Eu o vi implementado como uma fila para os serviços (consistência eventual), já que provavelmente você não está no controle do (s) serviço (s) e a imposição de gerenciadores de transações ou recursos transacionais é uma porcaria, na melhor das hipóteses, e provavelmente não é uma boa ideia em um ambiente SOA. Eu já vi isso principalmente no push móvel, onde você pode ou não ter uma conexão com o seu destino.
O ácido sobre microsserviços é difícil de entender, outra opção pode ser um ônibus, usando redis publicar / assinar ou um design de fila e postar uma vez no canal de entrada, então seus serviços de assinatura ou proxies de serviço avançam para os destinos e relatam sucesso fracasso. Você precisará monitorar falhas e ter um fluxo para isso também. Você também pode ter falhas em que a transação não é válida em um serviço, mas em outros dois, mas é apenas outro fluxo de falha que você precisará solucionar.
Não usar algo como "gerenciador de filas", que é o que eu acho que Redis causaria um gargalo? Ou pelo menos tem alto potencial também? Também não conheço outra maneira que você descreveu.
— 9136 johnny
Dependendo do volume do fluxo de dados, implementei um gerenciador de filas, que tenta novamente as transmissões até que o sucesso seja relatado ou publica uma notificação com falha e envia um alerta por SMS sobre a interrupção. Eu acho que também dependeria um pouco da janela de interrupção esperada (quanto tempo).
É para isso que serve o rabbitmq?
Use um canal de comunicação persistente
Em vez de HTTP, descarte as mensagens em uma fila altamente disponível e persistente. Por exemplo, Kafka. Enquanto o servidor de destino estiver disponível em algum momento, ele receberá a mensagem.
Você tem o compromisso de provisionar e administrar agora um subsistema complexo (a fila). Portanto, analise se isso vale a pena.
Recuar e tentar novamente
Peça ao chamador que mantenha a solicitação com falha (possivelmente persistida no disco) e tente periodicamente novamente. Nesse caso, é importante distinguir entre sua solicitação que causa uma falha e o serviço que está sendo desativado. O primeiro provavelmente é devido a um bug e deve ser registrado ... as novas tentativas provavelmente não farão diferença até que uma correção seja feita.
Detectar e compensar
Uma tarefa periódica verifica condições de consistência entre microsserviços. Por exemplo, a falha registra até as consultas diretas da API, conforme necessário. Se descobrir um problema (por exemplo, há um pedido, mas a remessa nunca recebeu a lista de embalagem), execute as etapas de compensação. Essas etapas podem estar criando um tíquete de suporte para uma correção manual, ou enviando um e-mail a alguém ou qualquer outra coisa.
Considere alternativas de design
Um caso como esse provavelmente exige um gateway de API para gerenciar chamadas para microsserviços afetados. Dessa forma, você controla quais táticas são usadas para mitigar esse problema. Você provavelmente não deseja sobrecarregar os clientes com esses detalhes de implementação. Consulte Padrão do disjuntor .
Como os microsserviços são independentes, sempre haverá algum caso de falha que pode resultar em inconsistência. Você precisa estar preparado para fazer correções manuais quando elas surgirem.
Se você precisar de consistência forte, os microsserviços não serão um bom ajuste. Se ainda estiver precisando de escalabilidade, convém analisar o sharding, onde dados relacionados podem ser colocados no mesmo shard para garantir a consistência. Você ainda pode expandir o IO adicionando shards.
Se você precisar de consistência forte e não tiver problemas de escalabilidade, use apenas serviços monolíticos. Use as bibliotecas como limites dentro do seu aplicativo para separar preocupações.
— 9139 johnny
RabbitMQ é a resposta para sua pergunta? Não. Poderia fazer parte de uma solução que atenda às suas necessidades, mas não resolverá o seu problema sozinho.
Apenas uma nota. Acho RabbitMQ não persiste as mensagens. É consumido e removido da fila, então NÃO. Se você precisar de persistência e tentar novamente, o RabbitMQ não ajudará.
Acho que o que você está descrevendo é o problema de consenso: você não deseja confirmar, a menos que cada participante da transação distribuída diga que a operação foi bem-sucedida. A solução simples para isso é o Commit Two Phase. Essencialmente, ele monitora a transação em cada sistema até que cada um reporte que a preparação foi bem-sucedida (Fase 1). Se todos os participantes da transação retornarem com sucesso, será solicitado a cada um que se comprometa; se algum deles retornar uma falha, será emitida uma reversão (Fase 2). Há um problema nisso que leva à solução mais complexa de confirmação trifásica. Você pode ler uma descrição muito melhor de cada um aqui: