El lugar en el que estoy trabajando es tratar de establecer algunas reglas básicas, y el debate que estamos teniendo ahora es bibliotecas locales versus servicios web para la reutilización de código. Los servicios web parecen ser la elección popular en la mayoría de las empresas, y hacia eso se inclinan la mayoría de los desarrolladores.
Simplemente no puedo ver cómo puede utilizar efectivamente los servicios web para cualquier trabajo serio. ¿Cómo puedo ejecutar de manera segura varias llamadas de servicio si no puedo usar una transacción?
Digamos que tengo un trabajo cron que capta clientes de nuestra base de datos que cumplen una determinada condición de la que deben ser notificados. Se les envía un fax, un correo electrónico y se crea un ticket para rastrear el problema internamente. Eso es 3 llamadas de servicio diferentes que sucederían para cada cliente en un bucle for.
Si se produce un error en algún lugar, es posible que, por ejemplo, se envíe un fax y un correo electrónico al cliente, pero no se cree un ticket. O peor, este trabajo cron podría contener un error que provoca que falle en el mismo punto cada vez, y envía correos electrónicos repetidamente al mismo cliente. Si las bibliotecas fueran todas locales, todo podría estar envuelto en una transacción, y nada de eso sucedería. Pero estamos usando servicios web en este ejemplo.
Tenga en cuenta que los métodos de correo electrónico y fax en realidad insertan los datos en tablas de colas respaldadas por bases de datos, que a su vez son manejadas por un proceso de trabajo cron separado. Por lo tanto, las llamadas a los métodos de servicio "enviar correo electrónico" y "enviar fax" podrían suspenderse sin efectos secundarios si fuera necesario.
Una opción es poner todo este fragmento de código en el servicio web en sí, para que el servicio web mismo llame a los métodos de creación de correo electrónico, fax y ticket en una transacción. Pero luego estamos creando un método de servicio web solo para el uso de una transacción; no hay una razón válida por la que necesitemos llamar a este método desde cualquier lugar, excepto este script cron.
¿Cómo manejarías generalmente este método?
fuente
Respuestas:
Lo que está describiendo es, de hecho, una transacción distribuida que implementa la confirmación en dos fases . Algunas plataformas de mensajería empresarial incluyen administradores de transacciones para admitir ese tipo de cosas, pero los productos concretos dependen de la plataforma / lenguaje. No tengo experiencia concreta con tales herramientas, pero espero que estos consejos ayuden.
fuente
Es interesante que a medida que participo en este Q&A particular, haya un hilo similar sobre los servicios que soportan múltiples plataformas en la lista de correo DDD / CQRS en el que estoy participando. Puedo repetir algunos de mis consejos aquí.
Una opción para admitir transacciones en un entorno heterogéneo es utilizar un mecanismo de transporte que admita transacciones y se admita en todas las plataformas desde las que se utilizará. El Advanced Message Queue Protocol (AMQP) admite transacciones y hay una API nativa para casi todos los idiomas que se usan comúnmente en la actualidad. RabbitMQ es un servidor que implementa AMQP y ha sido examinado en la industria como una solución sólida.
Aprovechar un sistema basado en RabbitMQ lo coloca en el camino para tener un ESB completo en caso de que necesite crecer. Publica mensajes en un canal y se suscribe a una cola. Donde eso se vuelve realmente poderoso es que entre el canal y la cola, puedes realizar muchas cosas interesantes. Un canal puede alimentar múltiples colas (pub / sub) una cola puede ser alimentada por múltiples canales, puede enrutar mensajes a diferentes colas en función del contenido, etc. etc.
Estaba leyendo sobre alternativas a las transacciones (que vienen con gastos generales y convierten una operación asincrónica en una operación de bloqueo). RabbitMQ admite lo que se llama confirmación de editor . Básicamente le permite registrar una devolución de llamada para un método publicado para manejar una transacción fallida. En su caso, podría deshacer las solicitudes de correo electrónico / fax y eliminar el ticket.
Por supuesto, la madriguera del conejo (perdón por el juego de palabras) va aún más profundo desde allí. Puede usar Rabbit para hacer orquestaciones complejas con servicios web internos y externos.
Para sus servicios web de cara al público, se vuelve muy simple. Su servicio (ya sea SOAP, REST o JSON) simplemente publica un mensaje en la cola de servicio apropiada y deja que su sistema interno lo maneje desde allí.
También hay una funcionalidad para crear un mensaje de solicitud / respuesta para aquellos escenarios en los que espera que la información vuelva rápidamente.
fuente
Las palabras clave que busca son 'coreografía de servicios web'.
Mira el artículo de Wikipedia al respecto.
fuente
La forma en que manejé esto en una aplicación de servicios que escribí fue crear un contenedor para manejar las transacciones necesarias. En mi caso, la solicitud del usuario, realizada por el sitio web, la aplicación de escritorio o el servicio de Windows, tenía que consultar un servicio web y, según el resultado y las opciones del usuario, tenía que actualizar una base de datos local y, opcionalmente, una remota a través de un servicio web. Luego tuvo que generar un informe para ser devuelto inmediatamente, enviado por correo electrónico y / o enviado por fax. Tenía control sobre la base de datos local, el correo electrónico y la generación de informes, pero ninguno en los servicios web o el servidor de fax.
La creación de un contenedor permitió un mejor control de transacciones y manejo de errores. También permitió una mejor seguridad al controlar el acceso a los servicios de red internos desde fuentes externas. En general, veo la necesidad de transacciones y administración del servicio como una razón válida para crear un contenedor apropiado para una solución única siempre que el código se reutilice correctamente (sin codificación de cortar y pegar).
fuente
No puedes
La pregunta que debe hacerse es: ¿cómo implemento las transacciones con el servicio web framework X? En este momento, solo estás asumiendo que es imposible.
fuente