Acabo de leer este artículo y estoy confundido.
Imaginemos 1 aplicación web y 1 aplicación distinta que actúe como "trabajador", ambas compartiendo la misma base de datos .
Oh, dije "compartir" ... pero ¿de qué advierte el artículo? :
Cuarto, compartir una base de datos entre aplicaciones (o servicios) es algo malo. Es demasiado tentador poner un estado amorfo compartido allí y antes de que te des cuenta tendrás un monstruo enormemente acoplado.
=> en desacuerdo. Hay algunos casos en los que distintas aplicaciones siguen siendo parte de la misma unidad y, por lo tanto, la noción de "problema de acoplamiento" no tiene sentido en este caso.
Continuemos: la aplicación web maneja las solicitudes HTTP del cliente y puede actualizar en cualquier momento algunos agregados (término DDD), generando los eventos de dominio correspondientes.
El objetivo del trabajador sería manejar esos eventos de dominio procesando los trabajos necesarios.
La cuestión es:
¿Cómo se deben pasar los datos de eventos al trabajador?
La primera solución, como promueve el artículo leído, sería utilizar RabbitMQ, que es un gran middleware orientado a mensajes.
El flujo de trabajo sería simple:
Cada vez que la web dyno genera un evento, lo publica a través de RabbitMQ, que alimenta al trabajador.
El inconveniente sería que nada garantiza la coherencia inmediata entre la confirmación de la actualización agregada y la publicación del evento, sin tratar los posibles fallos de envío ... o problemas de hardware; Esa es otra cuestión principal.
Ejemplo: sería posible que un evento se publicara sin un éxito de la actualización agregada ... resultando en un evento que representa una representación falsa del modelo de dominio.
Se podría argumentar que existe XA global (confirmación en dos fases), pero no es una solución que se adapte a todas las bases de datos o middlewares.
Entonces, ¿cuál podría ser una buena solución para garantizar esta consistencia inmediata? :
IMO, almacenando el evento en la base de datos, en la misma transacción local que la actualización agregada.
Se crearía un planificador asíncrono simple y sería responsable de consultar los eventos actuales no publicados desde la base de datos y enviarlos a RabbitMQ, que a su vez llena al trabajador.
Pero por qué necesita un planificador adicional en el lado de la aplicación web y por cierto: ¿por qué necesita RabbitMQ en este caso?
Con esta solución, parece lógico que RabbitMQ podría ser innecesario, especialmente porque la base de datos es compartida.
De hecho, cualquiera que sea el caso, vimos que la consistencia inmediata implica un sondeo de la base de datos.
Entonces, ¿por qué el trabajador no sería responsable directamente de esta encuesta?
Por lo tanto, me pregunto por qué tantos artículos en la web critican apenas las colas de la base de datos, mientras promueven el middleware orientado a mensajes.
Extracto del artículo:
Simple, use la herramienta adecuada para el trabajo: este escenario está pidiendo un sistema de mensajería. Resuelve todos los problemas descritos anteriormente; no más sondeo, entrega eficiente de mensajes, no es necesario borrar los mensajes completos de las colas y no hay estado compartido.
Y consistencia inmediata, ¿ignorada?
En resumen, realmente parece que sea cual sea el caso, es decir, la base de datos compartida o no, necesitamos un sondeo de la base de datos .
¿Me perdí algunas nociones críticas?
Gracias
Respuestas:
Si está creando una aplicación simple con poco tráfico, hay algo que decir acerca de mantener otro componente fuera de su sistema. Es muy probable que no usar un bus de mensajes sea la respuesta correcta para usted. Sin embargo, sugeriría construir su sistema de manera que pueda cambiar el sistema de colas basado en bases de datos por una solución de middleware. Estoy de acuerdo con el artículo. Una base de datos no es la herramienta adecuada para un sistema basado en colas, pero puede ser lo suficientemente buena para usted.
Los sistemas basados en colas como RabbitMq están construidos alrededor de una escala masiva en hardware moderado. Su arquitectura es capaz de lograr esto evitando procesos que hacen que el sistema de base de datos compatible con ACID sea lento por su naturaleza. Dado que un bus de mensajes solo necesita asegurarse de que un mensaje se almacena y procesa con éxito, no necesita molestarse en bloquear y escribir registros de transacciones. Ambos conceptos son absolutamente necesarios para un sistema ACID, pero a menudo son motivo de controversia.
En términos de rendimiento, todo se reduce a: usted tiene una tabla SQL. Muchas lecturas y muchas escrituras. Ambos requieren algún tipo de bloqueo para actualizar filas, páginas e índices. Su mecanismo de sondeo está constantemente bloqueando un índice para realizar búsquedas en él. Esto evita que sucedan escrituras; en el mejor de los casos están en cola. El código que realiza el procesamiento también se bloquea para actualizar el estado en la cola cuando se completan o fallan. Sí, puede hacer una optimización de consultas después de la optimización para que esto funcione, o puede usar un sistema diseñado específicamente para la carga de trabajo que está solicitando. Un RabbitMq come este tipo de carga de trabajo sin siquiera sudar; Además de eso, puede guardar su base de datos de la carga de trabajo, dándole más espacio para escalar haciendo otras cosas.
Otra cosa a tener en cuenta es que la mayoría de los sistemas de cola generalmente no usan una técnica de sondeo (algunos permiten HTTP, pero recomiendan evitar el uso para el lado de recepción). RabbitMq utiliza protocolos de red diseñados específicamente para buses de mensajes como AMPQ .
Editar: Agregar caso de uso.
La forma en que he usado Rabbit es que he tenido un punto final API que acepta un cambio que requiere una tabla de base de datos muy utilizada. Esta tabla está bajo constante discusión y, en ocasiones, no podrá guardar un cambio de manera oportuna desde la API. En cambio, lo que hago es escribir la solicitud de cambio en una cola y luego tener un servicio que maneja estos mensajes como pueden. Si se produce una contención en la base de datos, la cola simplemente crece y el procesamiento de mensajes se retrasa. Por lo general, el tiempo de procesamiento disminuye en el rango de 14 ms, pero en tiempos de alta contención obtenemos hasta 2-3 segundos.
fuente