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.
Respostas:
Algumas opções
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.
fonte
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:
http://the-paper-trail.org/blog/consensus-protocols-two-phase-commit/
http://the-paper-trail.org/blog/consensus-protocols-three-phase-commit/
fonte