¿cómo manejar / architect soa cuando el servicio no está disponible?

7

Supongamos que tengo un servicio de terceros llamado Cool.io que proporciona una API RESTful pero a menudo falla. Mis aplicaciones consumen esa API, pero cuando Cool.io falla, mi aplicación realmente no puede hacer mucho ... ¡pero debería!

Diga que creo un proxy para Cool.io y este proxy almacena una copia de los datos de Cool.io y proporciona puntos finales RESTful para mi aplicación. Supongamos que mi proxy tiene una fiabilidad del 100% o, al menos, más que la de Cool.io. Supongamos también que mi proxy no tiene problemas para propagar PUT / POST a Cool.io, y no hay problemas para recibir lo mismo de Cool.io (en otras palabras, no hay problemas de sincronización de datos entre mi proxy y Cool.io).

Esto desacopla la dependencia de mi aplicación en Cool.io, que se desactiva todo el tiempo ... pero no desacopla el proxy del servicio Cool.io. Como tal, cuando mi aplicación modifica algo en el proxy, los datos del proxy cambian e intentan enviar ese cambio a Cool.io.

Pero, si Cool.io está inactivo, esa solicitud solo produce un error de indisponibilidad (o una conexión fallida).

¿Cuál es la forma correcta de diseñar algo como esto? ¿Cómo los individuos como Amazon o Netflix desacoplan sus servicios de tal manera que una interrupción del servicio no afecte al consumidor, o si lo hace, lo hace con gracia?

¿Hay una cola de mensajes en orden aquí?

¿Existe una solución más sencilla que crear un proxy para el servicio no confiable?

    
pregunta ybakos 25.05.2012 - 22:38

3 respuestas

5

Creo que lo respondiste tú mismo: Message Queue. Necesita su proxy para poder esperar a que el servicio regrese y luego volver a enviar sus solicitudes. Por lo tanto, empujar las solicitudes en una cola. Haga que el administrador de colas haga un ping al servicio para verificar su estado y envíe los mensajes de la cola cuando esté activo. No elimine el mensaje de la cola hasta que obtenga una respuesta positiva de que el servicio lo procesó.

    
respondido por el Matthew Flynn 25.05.2012 - 22:49
2

Ya que su servicio es de lectura intensiva, usar un proxy de almacenamiento en caché parece una buena idea. Pero tenga cuidado: cuanto más intente retener la semántica del sistema original cuando el backend está inactivo, más complejo se volverá su sistema. Y, por lo general, cuanto más sorprendentes son sus modos de falla para el usuario final. Ambos factores a menudo motivarán la decisión de adoptar un proxy simple de solo lectura.

Incluso un proxy de solo lectura debería devolver una marca de tiempo con los datos, para indicar cuándo los datos fueron actualizados por última vez. Para HTTP puede codificar esto con IMS o un Etag; para otros sistemas dependerá del protocolo que esté utilizando. Rehusarse a proporcionar datos muy poco actualizados desde el proxy es una opción que puede hacer pero que no tiene que hacer.

En la capa de tu aplicación, deberás decidir qué hacer cuando el usuario quiera realizar una acción similar a una mutación en los datos de edad T segundos.

Creo que normalmente es mejor aceptar el cambio y devolver un error si el backend (Cool.io) no pudo procesar la solicitud. Si opta por rechazar sin intentarlo, tendrá problemas en los que la comprobación previa a la mutación encuentra el backend en un estado, pero el intento de aplicar el cambio lo encuentra en otro: esta situación es difícil de probar en su El conjunto de pruebas de regresión del sistema, por lo que mi consejo es no construir un sistema que intente hacerlo.

Si el backend no puede aplicar su cambio, su sistema podría tratar este error como definitivo o podría ofrecer intentar aplicar el cambio cuando se devuelva el servicio.

Como una optimización de la experiencia del usuario, cuando sabe que el proxy no ha podido obtener el servicio del servidor, puede mostrar advertencias en la interfaz del usuario, de modo que el usuario pueda evitar una entrada de datos que tarde mucho tiempo para encontrar el backend está abajo.

Si ofrece la posibilidad de aplicar un cambio fallido más adelante, los cambios que el usuario deseaba aplicar pero que no se pudieron aplicar a corto plazo deberán almacenarse. Puede almacenarlos en una cola, pero como señaló @ matthew-flynn, deberá manejar los cambios en cola duplicados (quizás en conflicto). Por lo tanto, es probable que tenga que "poner en cola" los cambios de forma consultable. Como en una tabla de base de datos de cambios no conciliados. Lo más sencillo es rechazar los cambios en los datos que, en sí mismos, no se han aplicado al backend. De lo contrario, el hecho de no aplicar un determinado cambio al backend puede requerir que se rechace más de un cambio a nivel de usuario.

Si es posible que un cambio en la cola no se aplique, deberá proporcionar algún tipo de funcionalidad en la que el usuario reconcilie los cambios fallidos.

Un caso particularmente interesante es cuando el backend acaba de aparecer y otro usuario ha enviado un cambio en conflicto, en vivo. Es decir, un nuevo cambio ha "superado" un cambio en cola. Podría considerar el bloqueo de todos los cambios realizados por los usuarios cuando haya cambios pendientes en cola. Una forma de lograrlo es que todos los cambios, en vivo o diferidos, utilicen la misma cola. Si lo haces, asegúrate de que los cambios de problemas no se puedan bloquear al principio de la cola.

Como notará de lo anterior, todo esto requiere claramente cambios en la semántica de la aplicación. No puede hacerlo invisiblemente en una capa proxy, a menos que rechace las mutaciones que no podrían aplicarse inmediatamente al backend. Y si el usuario hace una diferencia, ya sea que los datos estén nuevos o no, es posible que deba advertirles que están viendo datos obsoletos.

También preguntaste cómo los servicios grandes tratan esto. Una de las formas más populares es que los backends sean fragmentados por el ID de usuario, de modo que si una parte determinada del servicio no funciona, solo algunos usuarios se verán afectados. Esto es fácil de hacer para cosas como el servicio de datos estáticos (que en su mayoría no le importará quién eres) pero mucho más difícil para los servicios en los que los usuarios tienen relaciones de N a N (por ejemplo, cosas como Twitter, aunque en el caso de Twitter). la mayoría de las complejidades en torno a las mutaciones fallidas están ausentes).

    
respondido por el James Youngman 27.05.2012 - 19:26
0

Sus servicios deben ser autónomos y deben comunicarse entre sí mediante mensajes basados en eventos. Además de usar una solución basada en colas, sus datos deben ser descentralizados. Y evitar la orquestación del servicio.

Para lograr eso con el mínimo de dolor, descomponga su sistema en servicio a lo largo de su capacidades empresariales . Existen diferentes maneras de identificarlos, pero probablemente la más sencilla es tratar sus servicios como pasos que su empresa debe seguir para obtener un valor comercial. Aquí hay un ejemplo de usar esta técnica.

    
respondido por el Zapadlo 14.11.2017 - 20:19

Lea otras preguntas en las etiquetas