Esta es una pregunta clásica que me hicieron recientemente durante una entrevista Cómo llamar a múltiples servicios web y aún así preservar algún tipo de manejo de errores en el medio de la tarea. Hoy, en la informática de alto rendimiento, evitamos los compromisos de dos fases. Hace muchos años leí un artículo sobre lo que se llamó el "modelo de Starbuck" para las transacciones: piense en el proceso de ordenar, pagar, preparar y recibir el café que ordena en Starbuck ... Simplifico las cosas, pero un modelo de compromiso de dos fases sugiera que todo el proceso sería una única transacción de envoltura para todos los pasos involucrados hasta que reciba su café. Sin embargo, con este modelo, todos los empleados esperarían y dejarían de trabajar hasta que obtenga su café. ¿Ves la foto?
En cambio, el "modelo Starbuck" es más productivo siguiendo el modelo de "mejor esfuerzo" y compensando los errores en el proceso. Primero, ¡se aseguran de que pagues! Luego, hay colas de mensajes con su pedido adjunto a la taza. Si algo sale mal en el proceso, como si no obtuviera su café, no es lo que ordenó, etc., iniciamos el proceso de compensación y nos aseguramos de que obtenga lo que desea o le reembolse, este es el modelo más eficiente para aumentar la productividad.
A veces, Starbuck está desperdiciando un café, pero el proceso general es eficiente. Hay otros trucos para pensar cuando crea sus servicios web, como diseñarlos de una manera que se puedan llamar cualquier número de veces y aún así proporcionar el mismo resultado final. Entonces, mi recomendación es:
No sea demasiado bueno al definir sus servicios web (no estoy convencido de la exageración de los microservicios que está ocurriendo en estos días: demasiados riesgos de ir demasiado lejos);
Async aumenta el rendimiento, así que prefiera ser async, envíe notificaciones por correo electrónico siempre que sea posible.
Cree servicios más inteligentes para hacerlos "recuperables" cualquier cantidad de veces, procesando con un uid o taskid que seguirá el orden de abajo hacia arriba hasta el final, validando las reglas de negocio en cada paso;
Utilice colas de mensajes (JMS u otros) y desvíe a los procesadores de manejo de errores que aplicarán operaciones de "reversión" aplicando operaciones opuestas, por cierto, trabajar con orden asíncrono requerirá algún tipo de cola para validar el estado actual del proceso, así que considera eso;
En último recurso, (ya que puede no suceder con frecuencia), póngalo en una cola para el procesamiento manual de errores.
Volvamos al problema inicial que se publicó. Cree una cuenta y cree una billetera y asegúrese de que todo esté hecho.
Digamos que se llama a un servicio web para orquestar toda la operación.
El pseudo código del servicio web se vería así:
Llame al microservicio de creación de cuenta, pásele alguna información y una identificación de tarea única 1.1 El microservicio de creación de cuenta primero verificará si esa cuenta ya se creó. Una identificación de tarea está asociada con el registro de la cuenta. El microservicio detecta que la cuenta no existe, por lo que la crea y almacena la identificación de la tarea. NOTA: este servicio se puede llamar 2000 veces, siempre realizará el mismo resultado. El servicio responde con un "recibo que contiene información mínima para realizar una operación de deshacer si es necesario".
Llame a la creación de Wallet, dándole el ID de la cuenta y el ID de la tarea. Digamos que una condición no es válida y la creación de la billetera no se puede realizar. La llamada regresa con un error pero no se creó nada.
El orquestador es informado del error. Sabe que necesita abortar la creación de la cuenta, pero no lo hará por sí mismo. Le pedirá al servicio de billetera que lo haga pasando su "recibo de deshacer mínimo" recibido al final del paso 1.
El servicio de cuenta lee el recibo de deshacer y sabe cómo deshacer la operación; el recibo de deshacer puede incluso incluir información sobre otro microservicio que podría haberse denominado para hacer parte del trabajo. En esta situación, el recibo de deshacer podría contener el ID de la cuenta y posiblemente alguna información adicional requerida para realizar la operación opuesta. En nuestro caso, para simplificar las cosas, digamos simplemente eliminar la cuenta usando su ID de cuenta.
Ahora, digamos que el servicio web nunca recibió el éxito o el fracaso (en este caso) de que se realizó la acción de deshacer la creación de la cuenta. Simplemente volverá a llamar al servicio de deshacer de la cuenta. Y este servicio normalmente nunca debe fallar porque su objetivo es que la cuenta ya no exista. Por lo tanto, comprueba si existe y ve que no se puede hacer nada para deshacerlo. Por lo tanto, devuelve que la operación es un éxito.
El servicio web le informa al usuario que la cuenta no se pudo crear.
Este es un ejemplo sincrónico. Podríamos haberlo manejado de una manera diferente y poner el caso en una cola de mensajes dirigida a la mesa de ayuda si no queremos que el sistema recupere completamente el error ". He visto que esto se realiza en una compañía donde no hay suficiente Se podrían proporcionar ganchos al sistema de back-end para corregir situaciones. El servicio de asistencia recibió mensajes que contenían lo que se realizó con éxito y tenía suficiente información para arreglar cosas como nuestro recibo de deshacer podría usarse de una manera totalmente automática.
He realizado una búsqueda y el sitio web de Microsoft tiene una descripción de patrón para este enfoque. Se llama patrón de transacción compensatoria:
Patrón de transacción compensatoria