Solución:
Como se mencionó en las otras respuestas, no puede evitar que los mensajes duplicados provengan de SQS.
La mayoría de las veces, sus mensajes se entregarán a uno de sus consumidores una vez, pero voluntad encontrarse con duplicados en algún momento.
No creo que haya una respuesta fácil a esta pregunta, porque implica crear una arquitectura adecuada que pueda hacer frente a los duplicados, lo que significa que es de naturaleza idempotente.
Si todos los trabajadores de su arquitectura distribuida fueran idempotentes, sería fácil, porque no tendría que preocuparse por los duplicados. Pero en realidad, ese tipo de entorno no existe, en algún lugar del camino algo no podrá manejarlo.
Actualmente estoy trabajando en un proyecto en el que se me pide que resuelva esto y proponga un enfoque para manejarlo. Pensé que podría beneficiar a otros compartir mi pensamiento aquí. Y podría ser un buen lugar para obtener comentarios sobre mi pensamiento.
Tienda de hechos
Es una muy buena idea desarrollar servicios para que recopilen datos que, en teoría, puedan reproducirse para reproducir el mismo estado en todos los sistemas descendentes afectados.
Por ejemplo, supongamos que está creando un corredor de mensajes para una plataforma de negociación de acciones. (De hecho, he trabajado en un proyecto como este antes, fue horrible, pero también una buena experiencia de aprendizaje.)
Ahora digamos que entran las operaciones y hay 3 sistemas interesados en ello:
- Un mainframe de la vieja escuela que necesita mantenerse actualizado
- Un sistema que recopila todas las operaciones y las comparte con socios en un servidor FTP.
- El servicio que registra la operación y reasigna acciones al nuevo propietario.
Es un poco complicado, lo sé, pero la idea es que un mensaje (hecho) que llega tiene varios efectos distribuidos en sentido descendente.
Ahora imaginemos que mantenemos un almacén de datos, un registro de todas las operaciones que ingresan a nuestro corredor. Y que los 3 propietarios de servicios posteriores nos llaman para decirnos que han perdido todos sus datos de los últimos 3 días. La descarga de FTP tiene un retraso de 3 días, el mainframe tiene un retraso de 3 días y todas las operaciones tienen un retraso de 3 días.
Debido a que tenemos el almacén de hechos, teóricamente podríamos reproducir todos estos mensajes desde un momento determinado hasta un momento determinado. En nuestro ejemplo, eso sería desde hace 3 días hasta ahora. Y los servicios posteriores podrían ponerse al día.
Este ejemplo puede parecer un poco exagerado, pero estoy tratando de transmitir algo muy particular: los hechos son las cosas importantes a tener en cuenta, porque ahí es donde vamos a usar en nuestra arquitectura para luchar contra los duplicados.
Cómo la tienda de hechos nos ayuda con los mensajes duplicados
Siempre que implementes tu almacén de hechos en un nivel de persistencia que te brinde las partes de CA del teorema CAP, consistencia y disponibilidad, puedes hacer lo siguiente:
Tan pronto como se recibe un mensaje de una cola, verifica en su almacén de datos si ya ha visto este mensaje antes y, si lo ha hecho, si está bloqueado en este momento y en estado pendiente. En mi caso, usaré MongoDB para implementar mi almacén de hechos, ya que me siento muy cómodo con él, pero varias otras tecnologías de base de datos deberían poder manejar esto.
Si el hecho aún no existe, se inserta en el almacén de hechos, con un estado pendiente y un tiempo de vencimiento del bloqueo. Esto debe hacerse usando operaciones atómicas, ¡porque no quiere que esto suceda dos veces! Aquí es donde aseguras la idempotencia de tu servicio.
Caso feliz: ocurre la mayor parte del tiempo
Cuando la tienda de hechos vuelve a su servicio y le dice que el hecho no existía y que se creó un bloqueo, el servicio intenta hacer su trabajo. Una vez hecho esto, elimina el mensaje SQSy marca el hecho como completado.
Mensaje duplicado
Entonces eso es lo que sucede cuando llega un mensaje y no es un duplicado. Pero veamos cuándo llega un mensaje duplicado. El servicio lo recoge y le pide a la tienda de hechos que lo registre con un candado. La tienda de hechos le dice que ya existe y que está bloqueada. ¡El servicio ignora el mensaje y lo omite! Una vez que el otro trabajador haya procesado el mensaje, eliminará este mensaje de la cola y no lo volveremos a ver.
Caso de desastre: rara vez ocurre
Entonces, ¿qué sucede cuando un servicio registra el hecho por primera vez en la tienda, luego obtiene un candado por un período determinado, pero se cae? Bueno, SQS le presentará un mensaje nuevamente, si fue recogido, pero no eliminado dentro de un cierto período de tiempo después de haber sido servido de la cola. Es por eso que codificamos nuestro almacén de datos de modo que un servicio mantenga un bloqueo durante un tiempo limitado. Porque si falla, queremos que SQS presente el mensaje al servicio, u otra instancia del mismo en un momento posterior, permitiendo que ese servicio asuma que el hecho debe incorporarse al estado (ejecutar) nuevamente.
Amazon SQS presenta las colas FIFO con procesamiento de una sola vez y precios más bajos para las colas estándar
Uso del ID de deduplicación de mensajes de Amazon SQS El ID de deduplicación de mensajes es el token utilizado para la deduplicación de los mensajes enviados. Si un mensaje con un ID de deduplicación de mensajes en particular se envía correctamente, todos los mensajes enviados con el mismo ID de deduplicación de mensajes se aceptan correctamente, pero no se entregan durante el intervalo de deduplicación de 5 minutos.
Amazon SQS presenta las colas FIFO
Uso del ID de deduplicación de mensajes de Amazon SQS
No existe una forma a nivel de API de evitar que los mensajes duplicados se publiquen en una cola de SQS. Me temo que necesitaría manejar esto a nivel de aplicación.
Puede usar una tabla de DynamoDB para almacenar sus nombres de dominio en espera de ser rastreados y solo agregarlos a la cola si no están en DynamoDB, por ejemplo.