¿Cómo diseña su software que actualiza varios microservicios, si uno de ellos falla?

12

¿Existe algún patrón de diseño o práctica que pueda usar para ayudar con los servicios que están inactivos o inactivos, mientras que otros son estables?

¿Qué pasa si tengo tres microservicios, y dos de ellos son buenos, y uno muere justo en el medio de una POST? Dos recibirán la POST y uno no. No creo que pueda hacer transacciones porque estoy enviando mis solicitudes a un servicio.

¿Cómo diseño para eso? No quiero datos huérfanos en varias bases de datos.

johnny
fuente
66
No es un problema simple de resolver. Lo he visto implementado como una cola para los servicios (consistencia eventual), ya que lo más probable es que no tengas el control de los servicios, y la imposición de administradores de transacciones o capacidades transaccionales es un disparate en el mejor de los casos, y probablemente no sea una buena idea en un entorno SOA La mayoría de las veces lo he visto en torno a la inserción móvil, donde puede o no tener una conexión a su destino.
Mike
acid over microservices es un hueso duro de roer, otra opción podría ser un tipo de bus, usando redis de publicación / suscripción o un diseño de cola y publique una vez desde el canal entrante, luego sus servicios de suscripción o proxies de servicio empujan a los objetivos e informan éxito fracaso. Deberá controlar las fallas y también tener un flujo para ello. También puede tener fallas donde la transacción no es válida en un servicio pero sí en otros dos, pero es solo otro flujo de falla que deberá abordar.
Tim Cederquist
¿No usaría algo como "gestor de colas", que es lo que supongo que Redis causaría un cuello de botella? ¿O al menos tiene un alto potencial también? Tampoco conozco otra forma que la que describiste.
Johnny
Dependiendo del volumen de flujo de datos, he implementado un administrador de colas, que reintenta las transmisiones hasta que se informa el éxito o publica una notificación fallida y envía una alerta por SMS sobre la interrupción. Supongo que también dependería un poco de la ventana de interrupción esperada (cuánto tiempo).
htm11h
¿Para eso es algo como rabbitmq?
Johnny

Respuestas:

9

Algunas opciones

Use un canal de comunicación persistente

En lugar de HTTP, suelte los mensajes en una cola que esté altamente disponible y sea persistente. Por ejemplo, Kafka. Mientras el servidor de destino esté disponible en algún momento, recibirá el mensaje.

Ahora tiene el compromiso de aprovisionar y administrar un subsistema complejo (la cola). Así que asegúrese de analizar si esto vale la pena.

Retroceso y reintento

Haga que la persona que llama mantenga la solicitud fallida (posiblemente persistió en el disco) y vuelva a intentarlo periódicamente. En este caso, es importante distinguir entre su solicitud que causa un bloqueo y el servicio que simplemente no funciona. El primero probablemente se deba a un error y debe registrarse ... los reintentos probablemente no harán la diferencia hasta que se realice una corrección.

Detectar y compensar

Una tarea periódica verifica las condiciones de coherencia entre microservicios. Por ejemplo, la falla registra todo el camino para dirigir las consultas API según sea necesario. Si descubre un problema (por ejemplo, hay un pedido pero el envío nunca recibió la lista de empaque), realice los pasos de compensación. Esos pasos podrían ser crear un ticket de soporte para una solución manual, o enviar un correo electrónico a alguien, o lo que sea.

Considere alternativas de diseño

Un caso como este probablemente requiera una puerta de enlace API para administrar las llamadas a los microservicios afectados. De esa manera, usted controla qué tácticas se usan para mitigar este problema. Probablemente no desee cargar a los clientes con esos detalles de implementación. Ver Patrón de interruptor de circuito .

Debido a que los microservicios son independientes, siempre existirá algún caso de falla que pueda resultar en inconsistencia. Tienes que estar preparado para hacer arreglos manuales cuando surjan.

Si necesita una consistencia fuerte, entonces los microservicios no serán adecuados. Si aún necesita escalabilidad, es posible que desee buscar fragmentos donde los datos relacionados se puedan ubicar en el mismo fragmento para garantizar la coherencia. Todavía puede escalar IO agregando fragmentos.

Si necesita una fuerte consistencia y no tiene problemas de escalabilidad, simplemente use servicios monolíticos. Use las bibliotecas como límites dentro de su aplicación para separar las preocupaciones.

Kasey Speakman
fuente
¿Para esto es RabbitMQ?
Johnny
¿RabbitMQ es la respuesta a tu pregunta? No. Podría ser parte de una solución que satisfaga sus necesidades, pero no resolverá su problema solo.
Kasey Speakman
Solo una nota. Creo que RabbitMQ no persiste los mensajes. Se consume y se elimina de la cola, por lo que NO. Si necesita persistencia y volver a intentarlo, RabbitMQ no lo ayudará.
Laiv
2

Creo que lo que está describiendo es el problema del consenso: no desea comprometerse a menos que cada participante en la transacción distribuida diga que la operación fue exitosa. La solución simple a esto es el compromiso de dos fases. Esencialmente, organiza la transacción en cada sistema hasta que cada uno informa que la preparación fue exitosa (Fase 1). Si cada participante en la transacción devuelve el éxito, se le pide a cada uno que se comprometa; si alguno de ellos devuelve un error, se emite una reversión (Fase 2). Hay una arruga en esto que lo lleva a la solución de Compromiso trifásico más compleja. Puede leer una descripción mucho mejor de cada uno aquí:

http://the-paper-trail.org/blog/consensus-protocols-two-phase-commit/

http://the-paper-trail.org/blog/consensus-protocols-three-phase-commit/

iarejenius
fuente